【问题标题】:Circular Imports Motivation循环进口动机
【发布时间】:2018-10-08 10:57:03
【问题描述】:

我无法理解为什么 Django/python 不允许循环导入。不使用apps.get_model然后硬编码模型的标签和名称有什么办法吗?

假设我有两个模型AB,其中AB 有一个FK,B 有一些基于A 的属性。

型号A

from main import B
field = models.ForeignKey(B, default=None)

型号B

 # from main import A // this does not work
  @property
    def last_used(self):
        A = apps.get_model(app_label='main', model_name= 'A')

绕过它的唯一方法是上面的代码,如果我尝试导入 A 并使用 A.objects.filter 我得到 ImportError: cannot import nameerror。

我的问题是,当我重构代码时,查找所有那些硬编码的模型名称变得很麻烦。

这是一个糟糕的设计,我应该彻底改变模型背后的逻辑吗?

【问题讨论】:

  • 是 Python 不允许循环导入。
  • @WillemVanOnsem 同样的问题
  • 要回答您的问题,最好发布更多代码。有了这些小信息,没人知道你打算做什么。

标签: django django-models


【解决方案1】:

Python 不允许循环导入,因为它会引起麻烦。如果你写:

# module2.py
import module

Python 会先读取module.py 并定义类、函数等

但如果在module 中它说:

# module.py
import module2

那么这个就不能解决了:因为module2首先需要module,而module首先需要module2

由于ForeignKeys 经常需要这样的循环导入,Django 添加了一种方便的方法来指定模型:您可以使用字符串文字。例如:

# app1/models.py

class Model1(models.Model):
    model2 = ForeignKey('app2.Model2', on_delete=models.CASCADE)

而在app2/models.py 我们可以写:

# app2/models.py

class Model2(models.Model):
    model1 = ForeignKey('app1.Model1', on_delete=models.CASCADE)

所以你确实不需要需要导入模型,你可以使用一个字符串字面量作为标识符,Django会“打结”。

如果您需要循环引用,您可以将 import in 设为一个函数,例如:

def some_module(args):
    from main import A
    # ...
    pass

这将不会导致循环导入(当然,除非您立即调用该函数),此后import 被推迟直到 em> 你执行这个函数。

【讨论】:

    【解决方案2】:

    您根本不需要在 B 中导入 A。由于 A 具有到 B 的 ForeignKey,您可以使用 反向关系

    @property
    def last_used(self):
        return self.a_set.last()
    

    【讨论】:

    • 这正是我想要的!非常感谢,你拯救了我的一天和我未来的一天!
    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多