在定义模型之前先将ForeignKey定义到该模型

Vai*_*hal 2 python django django-models python-3.x

因此,我面临的情况是,我需要在定义模型之前创建模型的外键。考虑以下模型:

class Question(models.Model):
    """Model for question."""

    question_text = models.TextField(blank=True, null=True)
    answer = models.ForeignKey(Option, on_delete=models.PROTECT)  # Can't do this


class Option(models.Model):
    """Model for options of a question."""

    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    text = models.CharField(max_length=127)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我有一个模型来保存问题(文本及其答案)。另外,我还有另一个模型来保存与问题相关的一个选项。这样我就可以为问题的选项创建可变数量,其中一个是正确的。但我无法将正确的选项链接到模型,因为需要首先声明Question模型才能将每个选项链接到. 有什么方法可以实现这一点吗?QuestionOptionQuestion

更新

经过一番思考后,我弄清楚了我可以使用的模型结构,我还需要一个模型来获得答案。

class Question(models.Model):
    """Model for question."""
    ...


class Option(models.Model):
    """Model for options of a question."""
    ...

class Answer(models.Model):
    """Model for answers."""

    question = models.OneToOneField(Question, on_delete=models.CASCADE)
    answer = models.ForeignKey(Option, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)

但问题仍然是如何在定义模型之前引用模型(如果可能的话)。

cez*_*zar 5

这就是我重写您的代码示例的方式:

class Question(models.Model):
    """Model for question."""

    question_text = models.TextField(blank=True, null=True)
    answer = models.ForeignKey('Option', on_delete=models.PROTECT)  # Can't do this


class Option(models.Model):
    """Model for options of a question."""

    question = models.ForeignKey('Question', on_delete=models.CASCADE)
    text = models.CharField(max_length=127)
Run Code Online (Sandbox Code Playgroud)

请注意传递给 的第一个参数(粗体)ForeignKey。它是一个带有模型名称的字符串。

如果你检查 Django 的外键官方文档,你会看到那里有这样的解释:

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

我个人认为这是一个很好的实践,并且在所有模型类中一致地使用它,无论它们的定义顺序如何。好处是,当您重构代码时,您不必考虑顺序。

此外,您还可以参考其他应用程序中的模型:


class Foo(models.Model):
    bar = models.ForeignKey('baz.SomeModel', on_delete=models.DO_NOTHING)
Run Code Online (Sandbox Code Playgroud)

无需显式导入模块,例如:

from baz.models import SomeModel
Run Code Online (Sandbox Code Playgroud)

  • 兄弟,你是一个救星,如此简单的解决方案,我疯狂地想弄清楚如何做到这一点。 (2认同)