django模型递归导入 - 如何解决

9 投票
3 回答
4876 浏览
提问于 2025-04-17 13:10

我有一个模型叫project_phase

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

它引用了pmo_review_task(因为在保存时会创建一个pmo_review_task)

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

pmo_review_task又引用了sc_review_task,这个sc_review_task又引用了project_phase(因为在保存时会创建一个project_phase)

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

所以最后就变成了project_phase 引用 pmo_review_task,然后 pmo_review_task 引用 sc_review_task,再然后 sc_review_task 又引用 project_phase,这样就形成了一个循环,导致出现了这个错误:

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

我该怎么解决这个问题呢?

3 个回答

3

Django 1.9 及以上版本

在 Django 1.9 中,django.db.models 里的 get_model() 方法被移除了。

现在可以使用 django.apps.get_model() 来代替。

类似的问题可以参考: Django 1.9 中 django.db.models.loading.get_model() 的替代方法是什么?

如果你只是想用它来创建外键,可以直接用应用的标签名(用引号括起来)。

比如,不要这样写 from core.models import project_phase,而是要这样:

models.ForeignKey("core.project_phase")
7

save方法里面引入project_phase

每当代码执行的时候,这个引入就会被调用。

如果你把它放在全局模块的命名空间里(也就是文件的最上面),那么它会立刻被调用,这样就会出现你说的循环引入问题,因为一个文件引入了另一个文件,而那个文件又引入了最初的文件。

如果你把这个引入语句放在一个函数里面,它在引入文件的时候就不会被调用。

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.
20

有两种方法:

  1. 在一个方法里面导入模型(就像@YujiTomita建议的那样)。
  2. 使用 django.db.models 里的 get_model 函数,这个函数是专门用来懒加载模型的:

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

我更喜欢第二种方法,不过两种方法都可以。

撰写回答