Django - Circular model import issue

DjangoDjango Models

Django Problem Overview


I'm really not getting this, so if someone could explain how this works I'd very much appreciate it. I have two applications, Accounts and Theme... here is my settings list:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
	'accounts',
	'themes',
)

In accounts, I am trying to do this:

from themes.models import Theme

class Account(models.Model):
	ACTIVE_STATUS = 1
	DEACTIVE_STATUS = 2
	ARCHIVE_STATUS = 3
	STATUS_CHOICES = (
		(ACTIVE_STATUS, ('Active')),
		(DEACTIVE_STATUS, ('Deactive')),
		(ARCHIVE_STATUS, ('Archived')),
	)

	id = models.AutoField(primary_key=True)
	name = models.CharField(max_length=250)
	slug = models.SlugField(unique=True, verbose_name='URL Slug')
	status = models.IntegerField(choices=STATUS_CHOICES, default=ACTIVE_STATUS, max_length=1)
	owner = models.ForeignKey(User)
	enable_comments = models.BooleanField(default=True)
	theme = models.ForeignKey(Theme)
	date_created = models.DateTimeField(default=datetime.now)

And in my theme model:

class Theme(models.Model):
	id = models.AutoField(primary_key=True)
	name = models.CharField(max_length=250)
	slug = models.SlugField(unique=True, verbose_name='URL Slug')
	date_created = models.DateTimeField(default=datetime.now)
		
class Stylesheet(models.Model):
	id = models.AutoField(primary_key=True)
	account = models.ForeignKey(Account)
	date_created = models.DateTimeField(default=datetime.now)
	content = models.TextField()

Django is kicking out the following error:

from themes.models import Theme
ImportError: cannot import name Theme

Is this some kind of circular import issue? I've tried using a lazy reference, but that doesn't seem to work either!

Django Solutions


Solution 1 - Django

Remove the import of Theme and use the model name as a string instead.

theme = models.ForeignKey('themes.Theme')

Solution 2 - Django

Upto Django 1.7:

Use get_model function from django.db.models which is designed for lazy model imports.:

from django.db.models import get_model
MyModel = get_model('app_name', 'ModelName')

In your case:

from django.db.models import get_model
Theme = get_model('themes', 'Theme')

Now you can use Theme

For Django 1.7+:

from django.apps import apps
apps.get_model('app_label.model_name')

Solution 3 - Django

Something I haven't seen mentioned anywhere in sufficient detail is how to properly formulate the string inside ForeignKey when referencing a model in a different app. This string needs to be app_label.model_name. And, very importantly, the app_label is not the entire line in INSTALLED_APPS, but only the last component of it. So if your INSTALLED_APPS looks like this:

INSTALLED_APPS = (
...
    'path.to.app1',
    'another.path.to.app2'
)

then to include a ForeignKey to a model in app2 in an app1 model, you must do:

app2_themodel = ForeignKey('app2.TheModel')

I spent quite a long time trying to solve a circular import issue (so I couldn't just from another.path.to.app2.models import TheModel) before I stumbled onto this, google/SO was no help (all the examples had single component app paths), so hopefully this will help other django newbies.

Solution 4 - Django

Since Django 1.7 correct way is to go like this:

from django.apps import apps

YourModel = apps.get_model('your_app_name', 'YourModel')

See: https://docs.djangoproject.com/ja/1.9/ref/applications/#django.apps.apps.get_model

Solution 5 - Django

I had the same problem but on using MyModel = get_model('app_name', 'ModelName') I got a new error 'raise AppRegistryNotReady("Models aren't loaded yet.")'

I tried all the other methods on this page but none worked for me. The way I fixed it was to use: MyModel = get_model('app_name', 'ModelName') but actually in the class rather than outside of it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHanpanView Question on Stackoverflow
Solution 1 - DjangoIgnacio Vazquez-AbramsView Answer on Stackoverflow
Solution 2 - DjangoRanju RView Answer on Stackoverflow
Solution 3 - DjangoBogatyrView Answer on Stackoverflow
Solution 4 - DjangoandilabsView Answer on Stackoverflow
Solution 5 - Djangoryansl39View Answer on Stackoverflow