How does Django handle importing of apps? - python

I would like to know how Django's imports work. For example, in this code:
# in some_app/views.py
from another_app.models import UserModel
# another_app is another app of the same project
there's an import statement that imports UserModel from models.py in another_app (another app of the same project).
I was just wondering how Django handles this importing because usual Django project's directory structure looks like this:
.
├── another_app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
├── some_app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── some_project
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
some_app and another_app are separate directories.
I want to know how the importing works because I want to find a workaround for one of my projects that have separate directories but requires each other's functions.

If you register the app name in installed app in django settings you can easily handle most migrations and other stuff other wise you can just branch off from the folder of the app name.
What i recommend is making a separate directory named app and you can place all your app inside app director so the app and project directory gets separated easily and your import will also be easy
you can import in this manner after wards
from app.some_new_app_name.models import MyModel
from app.some_new_app_name_2.models import MyModel2

Related

How to create a django microservices monorepo?

Given this blog project which has posts and comments apps:
blog
├── blog
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── comments
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── posts
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py
I want to be able to run each of the apps (services) independently. The django-admin runserver runs the whole app which is not what my intention. I want to run and deploy services independently, each with its own db and port, and choose which services to start in advance. I'm aware that each app can have its own db specified in settings.py. Not sure about how to run services independently though. I also want the resulting project structure to be PyCharm-friendly, which means I can choose which services to run within the same project workspace.

Flask from .models import * giving "attempted relative import with no known parent package"

When in my app.py, I am trying to import something from models.py and when I use
from .models import *
but I'm receiving the following error on my shell
ImportError: attempted relative import with no known parent package
My directory tree looks as following:
└── PROJECT_FOLDER
├── README.md
├── __pycache__
│   ├── app.cpython-36.pyc
│   ├── app.cpython-38.pyc
│   ├── scraping.cpython-36.pyc
│   └── scraping.cpython-38.pyc
├── app.py
├── db.sqlite3
├── models.py
├── scraping.py
├── static
│   └── css
│   ├── bootstrap-theme.min.css
│   ├── bootstrap.min.css
│   ├── sign.css
│   └── theme.css
└── templates
├── base.html
└── index.html
I've tried putting a main.py in an outer folder and importing from PROJECT_FOLDER.models import *
but that hasn't worked.
I also have tried putting an __init__.py in my root directory.
Any help is appreciated. Thanks!

How to keep each celery class based task in separate file in django project?

I have setup celery in my django project using official documentation at
http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#using-celery-with-django
So my project structure is
└── mysite
├── db.sqlite3
├── manage.py
├── mysite
│   ├── celery.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── polls
├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   └── __init__.py
├── models.py
├── tasks.py
├── tests.py
└── views.py
polls is application
polls/tasks.py have class based celery task.
Currently tasks.py have many tasks so that file is too big. I want to keep each task in separate file like
mysite/polls/
├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   └── __init__.py
├── models.py
├── tasks # I want to keep easy task in separate file like this
│   ├── __init__.py
│   ├── download_task.py
│   ├── process_task.py
│   └── upload_task.py
├── tests.py
└── views.py
How to make this setup working?
That is 100% correct. In your tasks/__init__.py file, make sure to import the tasks from the other files:
from .download_task import *
from .process_task import *
# etc...
And then make sure you have the autodiscover_tasks call in your celery.py file to discover the tasks in each of your INSTALLED_APPS.

Django double import during tests

whenever I run Django tests, I fall into a double import trap with my models.
Every time I get
RuntimeError: Conflicting 'userdevice' models in application 'cart': <class 'cart.models.devices.UserDevice'> and <class 'fridge.libs.cart.models.devices.UserDevice'>
Minimal failing example is at https://www.dropbox.com/sh/m802q544cet5dui/AACRGOMQXWqxUzi92WfqfvYea?dl=0
My folder structure is
.
├── apps
│   ├── __init__.py
│   └── milk
│      ├── __init__.py
│      └── tests
│      ├── __init__.py
│      └── test_commands.py
├── __init__.py
├── libs
│   ├── cart
│   │   ├── __init__.py
│   │   └── models
│   │      ├── devices.py
│   │      └── __init__.py
│   └── __init__.py
├── Makefile
├── manage.py
└── settings
├── __init__.py
└── settings.py
I have apps and libs folders in INSTALLED_APPS.
My models/__init__.py file contains
from .devices import *
From test_commands.py I include model with
from cart.models import UserDevice
I read multiple questions here at SO and some articles on web. I was also debugging this for a few hours, so I know the problem is that my model is imported twice. Once during the Django project initialization as cart.models.devices.UserDevice and once by the unittest library as fridge.libs.cart.models.devices.UserDevice but I simply do not know how to fix this situation.
This is also causing more problems in files, which can be initialized only once during the app run, but I guess that the solution will be same as to this one.
I am using Django 1.10.8 as this is a legacy project but I experience the same on Django 2.0.7.
Python version is 3.5. OS is Ubuntu 16.04.
Thanks for any advice or hint. Nothing I found so far did not help.
Edit
So I experimented a bit and the problem persist even when no import are made in tests and even if there are no tests at all. Just running the tests will make the double import and RuntimeError happen
No-tests version: https://www.dropbox.com/sh/qqzg842rihbh5im/AADzay8up3d_rFKqy2OAsx1za?dl=0
New folder structure
.
├── __init__.py
├── libs
│   ├── cart
│   │   ├── __init__.py
│   │   └── models
│   │      ├── devices.py
│   │      └── __init__.py
│   └── __init__.py
├── Makefile
├── manage.py
└── settings
├── __init__.py
└── settings.py
Edit:
For the future's sake - content of libs/cart/models/devices.py is just simple Django model class
from django.db import models
class UserDevice(models.Model):
is_active = models.BooleanField(default=True)
class Meta:
app_label = 'cart'
I somehow "solved" the problem by deleting libs/__init__.py file. I am not sure why it was present in the project in the first place.

Access django sqlite db from external script

I want to prepopulate my db using an external script. The script is the following
# -*- coding:utf-8-*-
import os, sys
from random import choice
PROJECT_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__),'..','..'))
sys.path.append(PROJECT_DIR)
os.environ['DJANGO_SETTINGS_MODULE']='geoedu.settings'
from school.models import School
from student.models import Student
if __name__=='__main__':
student = Student(first_name=choice(first_names_males), last_name=choice(last_names_males),
father_name=choice(first_names_males), mother_name=choice(first_names_females),
mobile=choice(mobiles), telephone=choice(telephones))
student.save()
where the arguments in choice are lists with names and telephones. When i run it though i get the following error
django.db.utils.DatabaseError: no such table: student_student
The directory tree
geoedu
├── geoedu
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── settings.py
│   ├── settings.pyc
│   ├── urls.py
│   ├── urls.pyc
│   ├── wsgi.py
│   └── wsgi.pyc
├── geoedu.db
├── geoedu.sublime-project
├── geoedu.sublime-workspace
├── manage.py
├── school
│   ├── admin.py
│   ├── admin.pyc
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── models.py
│   ├── models.pyc
│   ├── tests.py
│   └── views.py
├── scripts
│   └── populate.py
└── student
├── admin.py
├── admin.pyc
├── __init__.py
├── __init__.pyc
├── models.py
├── models.pyc
├── tests.py
└── views.py
What it does is it creates a new geoedu.db inside the script folder and uses that(which is empty and has no student_student table ofcourse)
Why is that happening?The PROJECT_DIR is the correct one(printed it out) and is the root of the tree that is the geodedu on the top of all.
EDIT: new geoedu.db gets created when creating new student. If I comment out those lines geoedu.db doesn't get created.
Defining models in Django helps you to manipulate instances.
But, before, you have to create the table "skeleton" in your sqlite db
For this, you just need to synchronize the db with Django by doing :
python manage.py syncdb
This has to be done one time only.
In the future, you will probably needs to make your models evolve (thus needing similar db evolutions), at this time South - or adhoc schema evolution queries - will be useful (http://south.aeracode.org/) but as far as you're prototyping, you can just remove db and recreate it with good table by executing syncdb
The problem was that i hadn't used an absolute path for the database name in the settings.py file. I added this in the NAME of the database engine
'NAME':os.path.join(SETTINGS_DIR,'geoedu.db')
and everything worked as it should. PROJECT_DIR is
SETTINGS_DIR = os.path.dirname(__file__)
so the database is created inside settings folder. If you wanted inside projects folder you should do
'NAME':os.path.abspath(os.path.join(SETTINGS_DIR,'..','geoedu.db'))

Categories

Resources