django - circular import problem when executing a command - python

I'm developing a django application. Modules of importance to my problem are given below:
globals.py --> contains constants that are used throughout the application. SITE_NAME and SITE_DOMAIN are two of those and are used to fill some strings. Here is how I define them:
from django.contrib.sites.models import Site
...
SITE_DOMAIN = Site.objects.get_current().domain
SITE_NAME = Site.objects.get_current().name
models.py --> models live inside this module. imports some constants from globals.py
some_command.py --> a command that imports some constants from globals also.
when executed, the command imports a constant from globals.py and runs into a circular import problem: inside globals.py, get_current() from sites app is called, and sites app in turn imports models.py which has imports from globals.py as well.
EDIT:
The application runs flawlessly, without encountering this circular import issue. Importing globals.py from shell brings no problems. Even the command can be executed from the shell without calling manage.py.
So why does manage.py some_command fail due to a circular import?
Thanks in advance.

Is there any particular reason you need to store SITE_DOMAIN and SITE_NAME in globals.py? These are already available directly from the sites framework.
According to the docs, the site object is cached the first time you access it, so importing it and using it there directly doesn't hurt.

Related

Unresolved import models Django + Docker

I have a few simple classes in my Django app that are not loading/importing properly. I know that the code works as I am Dockerizing over an existing app. I am fairly sure this is a similar issue to this but I do not know how to update this to use the Python inside my Docker container. I am following this guide (so all settings/configuration is the same).
I have 2 classes: a custom user class and a Company model, and I am trying to add a foreign key on the user that links it to a particular Company. On the other side, I will have a many to many relationships (a company can have multiple users).
from core.models import Company
VS Code says "unresolved import" when I hover on core.models
I figured out (kind of) how to fix the problem. This thread was helpful, I added a setting to ignore unresolved imports, I also reordered my imports, also I was opening the folder that contained my app code (the root where the docker-compose.yml file lives) but I needed to open the actual code/source directory.
Setting:
"python.analysis.disabled": [
"unresolved-import"
]

Sharing PonyORM's db session across different python module

I initially started a small python project (Python, Tkinter amd PonyORM) and became larger that is why I decided to divide the code (used to be single file only) to several modules (e.g. main, form1, entity, database). Main acting as the main controller, form1 as an example can contain a tkinter Frame which can be used as an interface where the user can input data, entity contains the db.Enttiy mappings and database for the pony.Database instance along with its connection details. I think problem is that during import, I'm getting this error "pony.orm.core.ERDiagramError: Cannot define entity 'EmpInfo': database mapping has already been generated". Can you point me to any existing code how should be done.
Probably you import your modules in a wrong order. Any module which contains entity definitions should be imported before db.generate_mapping() call.
I think you should call db.generate_mapping() right before entering tk.mainloop() when all imports are already done.
A good approach to avoid this is rather than having your db.generate_mapping() call happening at a module's top-level code, have a function that a module exports that calls db.generate_mapping() after all other modules have been imported.
The pattern I use is to put all of my db.Entity subclasses into a single module named model, and then at the bottom of model.py is:
def setup():
""" Set up the database """
db.bind(**database_config, create_db=True)
db.generate_mapping(create_tables=True)
This function is called by my application's own startup (which is also responsible for setting up database_config). This way the correct import and setup order can be guaranteed.
The db object itself is also owned by this model module; if I need to use it somewhere else I import model and use model.db.
If you want to further separate things out (with different model classes living in different modules) you can have a module that owns db, then your separate model modules, and then a third module that imports db and the models and provides the setup function. For example, your directory structure could look like this:
model/
__init__.py -- imports all of the model sub-modules and provides a setup function
db.py -- provides the db object itself and any common entities objects that everyone else needs
form1.py, form2.py, etc. -- imports db and uses its database object to define the entities
Then your main app can do something like:
import model
model.setup()

How do I avoid naming clashes within Python's module system?

In my Django project I have an app called profile, which mostly contains my profile.models.UserProfile class for additional information on User objects (may seem familiar to Django folks). Now I've put some initialization code into profile/__init__.py (some signals) and have ran into a problem: Django tells me that a table called hotshot_profile has not been found.
After literally hours of searching, I traced the problem back to importing order. Running python -v manage.py test I've found the following:
import nose.plugins.prof # precompiled from /home/rassie/.virtualenvs/myproject/lib/python2.6/site-packages/nose/plugins/prof.pyc
import hotshot # directory /usr/lib64/python2.6/hotshot
import hotshot # precompiled from /usr/lib64/python2.6/hotshot/__init__.pyc
dlopen("/home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so", 2);
import _hotshot # dynamically loaded from /home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so
import hotshot.stats # from /usr/lib64/python2.6/hotshot/stats.py
import profile # directory /home/rassie/MyProject/apps/profile
import profile # precompiled from /home/rassie/MyProject/apps/profile/__init__.pyc
So my Nose runner imports the nose.plugins.prof (even though this plugin is off), imports hotshot, which tries to import profile. However, profile gets imported from my project, while it ready should have been imported from system Python.
Obviously, my own profile module clashes with system profile module. I obviously can't exclude every module name that comes bundled with Python from my own programming. So the question is, where do I go from here? Do I have to create a myproject namespace for all of my apps? Will Django work with that?
PS: Table's name hotshot_profile seems to come from a further yet-to-be-fully-analyzed naming clash with a Profile class from pybb, which I'm also using in my project. But that's out of this question's scope.
You should never import your own modules in the form import mymodule (relative imports). Instead you should always use import myproject.mymodule instead (absolute imports). This avoids all name clashes.

Model imports failing between apps in django (circular imports?)

I am having problems importing models between my apps in my current django project. When trying to run the dev server or sync the database, I receive the error:
File "/path/to/Project/../Project/app1/models.py", line 3, in <module>
class SomeModel(Thing):
NameError: name 'Thing' is not defined
Thing is defined in Project/main/models.py which I import into Project/app1/models.py via:
from project.main.models import Thing
I am aware that this sort of thing can be the result of python preventing circular imports.
Currently I have three django apps: main, app1, app2
The imports for each app are like so:
main:
from project.app1.models import AnotherThing
app1:
from project.main.models import Thing
app2:
from project.main.models import Thing
from project.app1 import Something
I suspect that importing models from app1 into app2 is causing the problem, since both of those apps import models from main, which in turn imports models from app1, etc.
If this is the case - what other methods can I use to achieve the same effect as these imports?
Is there a more accepted way of organizing things so that I won't run into this?
If you want to subclass those models, you need to remove circular dependency. Refactor common stuff into another module, and make those two import that instead of each other. If the model is only used as a foreign key, you can use string instead of an object to defer the import (e.g. ForeignKey('app.Model') — see documentation for details).

How can I import a specific module with an ambiguous name?

This happens in Django context, but the question is not Django specific.
I'm trying to split my big urls.py into smaller and more manageable chunks (app includes, third-party modules, search, admin, development and so on). So instead of urls.py, I'm using urls/ directory now, with urls/__init__.py containing code like this:
import admin
urlpatterns += admin.urlpatterns
Now I've got into trouble with third-party modules. For example, I'm overriding a bunch of URLs and views for django-messages, and so I've put all of it into urls/messages.py. It turns out, I can't import django-messages' views then, since
from messages.views import inbox
inside urls/messages.py tries to import from local directory first, finds a messages module, but can't import messages.views then, since urls/messages/views.py is obviously absent. I wouldn't like having to rename my modules to something like urls.messages_urls, but I haven't found a way to explicitely tell Python to import the "other" messages.views. Neither would I like to specify my imported views via strings, even though I can do that in Django.
How can I solve this situation cleanly?
This is the wrong way to do it.
Django has a method for splitting urls.py into separate files, and that is to use include(). Keep the urls for each application in its own urls.py, and include them into the main one.
For those who could not find it, I was hitting ambiguous import errors. For example, in a django project, let's say I have this tree :
tax module
models module
init.py
tax.py
foo.py
In init.py, I want to import tax.models.tax.Tax.
So I write :
from tax.models.tax import Tax
But python does not find the correct import (it looks for models inside tax.models) and throws
ImportError: No module named models
You have indeed understood that it's all about relative imports. python first looks in the current module. If the first part of your import exists in the current module, it fails.
This behaviour has been fixed in Python 2.5 (and may have become default in Python 3.0), you just have to add :
from __future__ import absolute_import
before your absolute imports.
Have a look at Python 2.5 introduces absolute imports for more thorough information.
Have you tried:
from django.contrib.messages.views import inbox
Untested, but I'd think the full import would work as expected.

Categories

Resources