Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django models recursive imports - how to resolve

I have a model project_phase:

    from django.db import models
    from django.utils import simplejson
    from core.models import pmo_review_task

it references pmo_review_task (because it creates a pmo_review_task in its save ovewrite)

from django.db import models
from datetime import datetime
from django.contrib.auth.models import User
from core.models import sc_review_task

which references sc_review_task that references project_phase (because it creates a project_phase in its save ovewrite)

from django.db import models
from core.models import project_phase

so it ends up project_phase imports pmo_review_task imports sc_review_task imports project_phase and I guess it loops up somehow generating this error:

Unhandled exception in thread started by <bound method Command.inner_run of <django.core.management.commands.runserver.Command object at 0x010ACFB0>>
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\core\management\commands\runserver.py", line 88, in inner_run
    self.validate(display_num_errors=True)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "C:\Python27\lib\site-packages\django\core\management\validation.py", line 35, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "C:\Python27\lib\site-packages\django\db\models\loading.py", line 146, in get_app_errors
    self._populate()
  File "C:\Python27\lib\site-packages\django\db\models\loading.py", line 64, in _populate
    self.load_app(app_name)
  File "C:\Python27\lib\site-packages\django\db\models\loading.py", line 78, in load_app
    models = import_module('.models', app_name)
  File "C:\Python27\lib\site-packages\django\utils\importlib.py", line 35, in import_module
    __import__(name)
  File "C:\work\Portman\core\models\__init__.py", line 4, in <module>
    from pmo_review_task import pmo_review_task
  File "C:\work\Portman\core\models\pmo_review_task.py", line 5, in <module>
    from core.models import sc_review_task
  File "C:\work\Portman\core\models\sc_review_task.py", line 3, in <module>
    from core.models import project_phase
  File "C:\work\Portman\core\models\project_phase.py", line 4, in <module>
    from core.models import pmo_review_task
ImportError: cannot import name pmo_review_task

how do I overcome this?

like image 536
abolotnov Avatar asked Feb 17 '12 07:02

abolotnov


People also ask

What does Django DB models model clean () do?

The first step full_clean() performs is to clean each individual field. This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

What is recursive relationship in Django?

In Django, a recursive many-to-many relationship is a ManyToManyField that points to the same model in which it's defined ('self'). A symmetrical relationship is one in where, when a. contacts = [b], a is in b. contacts.

What is from Django DB import models?

In short, Django Models is the SQL of Database one uses with Django. SQL (Structured Query Language) is complex and involves a lot of different queries for creating, deleting, updating or any other stuff related to database. Django models simplify the tasks and organize tables into models.

What is Django ForeignKey model?

ForeignKey is a Django ORM field-to-column mapping for creating and working with relationships between tables in relational databases. ForeignKey is defined within the django. db. models. related module but is typically referenced from django.


3 Answers

Two ways:

  1. To import a model inside a method (as @YujiTomita suggested).
  2. To use get_model function from django.db.models which is designed for lazy model imports.:

    project_phase = get_model('core', 'project_phase')
    

I prefer the second one, but both methods are ok.

like image 163
DrTyrsa Avatar answered Oct 06 '22 01:10

DrTyrsa


import project_phase inside the save method.

The import is called whenever the code is executed.

If it's in the global module namespace (at the top) then it's called right away and you'll have circular import problems as you describe because one file imports another file which imports the original file.

If you put the problem import statement inside a function, it is /not/ called upon importing the file.

import foo # executed upon importing this file. 

def import_foo_when_called():
    import foo # only executed when function is called, thus no problems when 
               # another module imports this file.
like image 38
Yuji 'Tomita' Tomita Avatar answered Oct 06 '22 00:10

Yuji 'Tomita' Tomita


Django 1.9 and above

As get_model() in django.db.models has been removed in 1.9.

Use django.apps.get_model()

Similar Question: What is the equivalent of django.db.models.loading.get_model() in Django 1.9?

or use application label in quotes if you are just using it to create foreignkey.

Instead of from core.models import project_phase do

models.ForeignKey("core.project_phase")
like image 42
Nagashayan Avatar answered Oct 06 '22 01:10

Nagashayan