大家好!
关于我遇到的一件事的简单问题,我理解了这个问题,但无法弄清楚为什么?
不仅我不知道例如model1
是否必须具有model2
或model2
的ForeignKey
使用 ManyToManyField
到 model1
(困惑)。
假设我们有两(2)个模型文件和三(3)个类模型,app1.models.py
,其中[Model1
、ModelA
] 和 app2.models.py
以及 [Model2
]。
app1.models.py
from app2.models import Model2
class Model1(models.Model):
field1 = models.ForeignKey(Model2)
app2.models.py
from app1.models import ModelA
class Model2(models.Model):
field2 = models.ForeignKey(ModelA)
这肯定会引发错误ImportError
,
但如果我这样做:
class Model1(models.Model):
field1 = models.ForeignKey("app2.Model2")
<小时/>
class Model2(models.Model):
field2 = models.ForeignKey("app1.ModelA")
这会很好用
到底为什么?
我知道我可以在所需的文件中创建模型,但我想要的是了解为什么一个模型有效,而另一个模型无效。
谢谢!
最佳答案
import
语句实际上是可执行语句。如果您要求导入foo.bar.qux
,那么Python将首先检查它是否已经导入该文件(在sys.modules
中)。
如果尚未导入该模块,它将首先搜索该模块对应的文件。如果找不到该文件,我们会得到一个ImportError
,在其他情况下,Python 将打开相应的文件,并“导入它”。
导入意味着它将执行文件中的所有语句(从上到下)。但现在想象一下,您必须保存彼此需要的文件。在这种情况下,文件 A
需要(完全)导入文件 B
。但是 B
需要(完全)导入文件 A
。没有办法解决这个问题:因为文件末尾可能有语句,可以更改 class
定义等。但是我们已经达到了 import
语句,这是模块完全加载的“契约(Contract)”。所以这基本上是“先有鸡还是先有蛋”的问题。
但是,我们可以通过推迟链接来解决此类循环导入。而不是将引用传递给类。例如,我们可以传递某种 token (Django 使用字符串,但可能有不同的方式)。现在字符串不会引入问题,因为在我们开始解释之前,Python 的“内置库”已经加载到内存中。
所有模型类加载到内存后,Django 将执行“链接”阶段。加载阶段结束后,所有 models.py
文件都会加载到内存中,因此现在我们可以用对类的引用替换字符串。因此,Django 基本上通过推迟将 ForeignKey
链接到真实的类对象来解决该问题。
关于python - 这里导入错误的具体原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50686164/