I know my question probably deals with mutual/circular imports, and I did search SO before posting. The only solution I found that currently solves my problem is to move imports to the end of one of the files, just before the imported functions are actually used. But I've also read that's highly unrecommended.
A recommended solution, to just do:
in A.py
-> import B
and in B.py
-> import A
And then access the functions, isn't working.
So I have three apps in my Django app: "core", "notifications", and "accounts". Here are snippets from them:
core.models:
from django.db import models
from django.contrib.auth.models import User
import notifications.models
from z_misc import general_scripts
# Create your models here.
class BaseModel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
Here's how I use Notification
in core.models
:
# inspect mb for each artist
### Assume class is defined and @classmethod is intended, having some formatting pains here
@classmethod
def refresh_from_mb(cls):
artists = cls.get_artists_with_subs()
for artist in artists:
added_rgs = general_scripts.refresh_artist(artist.mbid)
for rg in added_rgs:
new_notification = Notification(artist_id=artist.id, release_group=rg)
new_notification.save()
notification.models:
from django.db import models
import core.models
import accounts.models
class Notification(core.models.BaseModel):
artist_id = models.OneToOneField(core.models.Artist, related_name="artist_notifications", null=False)
release_group = models.OneToOneField(core.models.ReleaseGroup, related_name="rg_notifications", null=False)
def get_rg_type(self):
return self.release_group.type
accounts.models:
from django.db import models
from django.contrib.auth.models import User
import core.models
from django.db.models import Q
# Create your models here.
class UserProfile(core.models.BaseModel):
#TODO: add email_activated = models.BooleanField(default=False)
user = models.OneToOneField(User, related_name="user_profile")
As you can see, I'm following the advice not do from
and then import
, but to rather import
and then use the full notation. It doesn't work. The full error traceback is:
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x10fa9af28>
Traceback (most recent call last):
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
autoreload.raise_last_exception()
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 251, in raise_last_exception
six.reraise(*_exception)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models()
File "/Users/username/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/Users/username/.pyenv/versions/3.6.1/lib/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 978, in _gcd_import
File "<frozen importlib._bootstrap>", line 961, in _find_and_load
File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
File "/Users/username/PycharmProjects/artist_notify/core/models.py", line 3, in <module>
import notifications.models
File "/Users/username/PycharmProjects/artist_notify/notifications/models.py", line 3, in <module>
import accounts.models
File "/Users/username/PycharmProjects/artist_notify/accounts/models.py", line 8, in <module>
class UserProfile(core.models.BaseModel):
AttributeError: module 'core' has no attribute 'models'
I'm not sure what can I do to solve it at this point. Except start moving import statements to the middle/end of files, which seems like a big no-no.
Please don't suggest I use from app.models import ModelName
, because that's what I was using before until errors started coming out because of circular imports.