字符串和不带字符串的django foreigin键之间有什么区别?

时间:2019-07-07 13:38:40

标签: django django-models

我不明白为什么人们用两种方式写外键,这的目的是什么?它们是相同还是不同?

我注意到有些人这样写道:

author = models.ForeignKey(Author, on_delete=models.CASCADE)

有些人这样写:

author = models.ForeignKey('Author', on_delete=models.CASCADE)

这些之间有什么区别?这样写有什么特殊目的吗?还是两者都一样?

2 个答案:

答案 0 :(得分:2)

  

这些之间有什么区别?这样写有什么特殊目的吗?还是两者都一样?

它们都导致相同的链接,是的。字符串稍后将被“解析”,最终ForeignKey将指向Author模型。

但是,如果需要定义目标模型,则有时有时仅使用字符串进行引用。例如,对于循环引用。

例如,假设您定义如下关系:

class Author(models.Model):
    name = models.CharField(max_length=128)
    favorite_book = models.ForeignKey(Book, null=True, on_delete=models.SET_NULL)

class Book(models.Model):
    title = models.CharField(max_length=128)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

这里Book指的是Author,而Author指的是Book。但是,由于在构造Book时并未构造ForeignKey类,因此将得到NameError

在定义Author之后,我们不能再定义Book,因为那样的话,我们在构造Author之前就先参考了{{1} }。

但是我们可以在这里使用字符串,避免使用循环引用,例如:

NameError

通过使用字符串,对于Python解释器来说是很好的,因为您不使用尚未定义的标识符,并且Django将在加载模型时将字符串替换为对相应模型的引用

documentation on a ForeignKey [Django-doc]

  

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

如果模型是在另一个应用程序中定义的,则可以使用class Author(models.Model): name = models.CharField(max_length=128) favorite_book = models.ForeignKey('Book', null=True, on_delete=models.SET_NULL) class Book(models.Model): title = models.CharField(max_length=128) author = models.ForeignKey(Author, on_delete=models.CASCADE)来引用它。

答案 1 :(得分:1)

假设您已将模型布置如下:

models/
    __init__.py
    model_a.py
    model_b.py

当您的应用程序具有很多模型并且希望更好地组织代码时,这是常见的布局。现在说ModelA有一个ModelB的外键,而ModelB有一个ModelA的外键。您不能同时导入两个文件,因为要进行循环导入。

通过字符串引用另一个模型使您可以“延迟”引用尚未加载的另一个模型,这解决了循环导入的问题