导入错误到底是什么原因?

时间:2018-06-04 17:49:41

标签: python django

Hello Awesome People!

关于我遇到的事情并理解问题但却无法弄清楚原因的简单问题?

我不仅不知道例如model1ForeignKeymodel2还是model2 ManyToManyFieldmodel1 (困惑)。

假设我们有两(2)个模型文件三(3)类模型app1.models.py [Model1,{{ 1}}]和ModelA与[app2.models.py]。

app1.models.py

Model2

app2.models.py

from app2.models import Model2

class Model1(models.Model):
    field1 = models.ForeignKey(Model2)

这肯定会引发错误from app1.models import ModelA class Model2(models.Model): field2 = models.ForeignKey(ModelA)

但如果我这样做:

ImportError
class Model1(models.Model):
    field1 = models.ForeignKey("app2.Model2")

这样可以正常使用

为什么到底?

我知道我可以在所需的文件中创建模型,但我想要的是理解为什么一个有效,而不是另一个。

谢谢!

2 个答案:

答案 0 :(得分:2)

import语句实际上是可执行语句。如果您要求import foo.bar.qux,那么Python将首先检查它是否已导入该文件(在sys.modules中)。

如果尚未导入该模块,它将首先执行搜索与模块对应的文件。如果找不到文件,我们会得到一个ImportError,在另一种情况下,Python会打开相应的文件,并且#34;导入它"。

导入意味着它将执行文件中的所有语句(从上到下)。但现在想象你必须要有彼此需要的文件。在这种情况下,文件A需要(完全)导入文件B。但B要求(完全)导入文件A。没有办法解决这个问题:因为文件末尾可能有语句,这会改变class定义等等。但是我们已经达到import语句,这是一个&#34 ;合同"该模块已完全加载。所以这基本上是" 鸡与鸡蛋" -problem。

然而,我们可以通过推迟链接来解决这种循环导入。而不是将引用传递给类。例如,我们可以传递某种令牌(Django使用字符串,但可能有不同的方式)。现在字符串不会引入问题,因为在我们开始解释之前,"内置库" Python已经加载到内存中了。

将所有模型类加载到内存后,Django将执行" 链接"相。在加载阶段之后,所有models.py文件都被加载到内存中,所以现在我们可以用对类的引用替换字符串。所以Django基本上通过推迟将ForeignKey s链接到真实类对象来解决问题。

答案 1 :(得分:1)

符号

field1 = models.ForeignKey(Model2)

表示已经创建了“Model2”。但是python在一个序列中创建了两个对象。当python创建ModelA时会遇到此错误,而ModelA试图指向尚未存在的ModelB。 您可以使用

解决此问题
field1 = models.ForeignKey("app2.Model2")

你也可以在Django documentation

中看到这个
  

如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身。