How to solve the circular import error in django?

Question:

I know the error is probably due to circular import error but not having much knowledge about it I am not able to correct it. I have tried using the methods given in similar questions but couldn’t resolve it.The project has two apps consult and main and I need to import their models into each other,

consult/models.py

from django.db import models
from django.contrib.auth.models import User
from main.models import Customer


class Question(models.Model):
    name = models.ForeignKey(Customer, on_delete=models.CASCADE)
    type = models.CharField(max_length=100, default="SkinCare")
    title = models.CharField(max_length=1000)
    body = models.CharField(max_length=1000000)
    image = models.FileField(blank=True, default=None)
    time = models.DateTimeField()
    deltatime = models.IntegerField(default=0)

    def __str__(self):
        return str(self.time)


class Reply(models.Model):
    name = models.ForeignKey(Question, on_delete=models.CASCADE)
    user = models.ForeignKey(Customer, on_delete=models.CASCADE)
    text = models.CharField(max_length=10000000000)
    like = models.IntegerField(default=0)
    dislike = models.IntegerField(default=0)
    time = models.DateTimeField()
    deltatime = models.IntegerField(default=0)

    def __str__(self):
        return str(self.time)

main/models.py

from django.contrib.auth.models import User
from django.db import models
from consult.models import Question, Reply


class Customer(models.Model):
    name = models.ForeignKey(User, null=True)
    gender = models.CharField(max_length=100)
    skin_type = models.CharField(max_length=1000)
    hair_type = models.CharField(max_length=1000)
    bookmarked = models.ManyToManyField(Question)

    def __str__(self):
        return str(self.name)

When I run try to migrate the appps the following error comes:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libsite-packagesdjango-1.10.4-
py3.5.eggdjangocoremanagement__init__.py", line 367, in execute_from_
command_line
    utility.execute()
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libsite-packagesdjango-1.10.4-
py3.5.eggdjangocoremanagement__init__.py", line 341, in execute
django.setup()
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libsite-packagesdjango-1.10.4-py3.5.eggdjango__init__.py", line 27, 
in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libsite-packagesdjango-1.10.4-py3.5.eggdjangoappsregistry.py", line 
108, in populate
    app_config.import_models(all_models)
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libsite-packagesdjango-1.10.4-py3.5.eggdjangoappsconfig.py", line 
199, in import_models
    self.models_module = import_module(models_module_name)
  File "C:UsersNikhil KhandelwalAppDataLocalProgramsPythonPython35-
32libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in 
_call_with_frames_removed
  File "C:New folderWebDzeroveyconsultmodels.py", line 3, in <module>
    from main.models import Customer
  File "C:New folderWebDzeroveymainmodels.py", line 3, in <module>
    from consult.models import Question, Reply
ImportError: cannot import name 'Question'

Please answer considering that I am a beginner in Django, Thanking you in Advance 🙂

Asked By: Nikhil Khandelwal

||

Answers:

Try changing your imports into this:
in consult/models.py

import main.models.Customer

in main/models.py

import consult.models.Question
import consult.models.Reply

Then instead of Customer you use main.models.Customer and instead of Question or Reply you use import consult.models.Question and consult.models.Reply

Answered By: omu_negru

Use to='<app_lable>.<Model Name>' in Foreignkey and ManytoMany Fields

Remove import models from file add foreignkey and manytomany fields in model like i did in below code.to='consult.Question'
When we create migrations from makemifration command that use hardcode model name in migration file, So use same way to write Foreignkey and Manytomany field

from django.contrib.auth.models import User 
from django.db import models
class Customer(models.Model): 
    name = models.ForeignKey(User, null=True) 
    gender = models.CharField(max_length=100)
    skin_type = models.CharField(max_length=1000)
    hair_type = models.CharField(max_length=1000)
    bookmarked = models.ManyToManyField(to='consult.Question')

    def __str__(self):
        return str(self.name)
Answered By: Neeraj Kumar

Another way to resolve circular imports is to do:

from django.apps import apps
MyModel = apps.get_model('myapp', 'MyModel')
Answered By: Craig Wallace

You can do this remove from main.models import Customer
and in the class

class Question(models.Model):
    name = models.ForeignKey("main.Customer",related_name="customerQuestion", on_delete=models.CASCADE)

class Reply(models.Model):
    user = models.ForeignKey("main.Customer",related_name="customerReply", on_delete=models.CASCADE)
Answered By: asupriatna