Django:OneToOneField - RelatedObjectDoesNotExist

Django : OneToOneField - RelatedObjectDoesNotExist

我的模型中有以下两个 类:

class Answer(models.Model):
    answer = models.CharField(max_length=300)
    question = models.ForeignKey('Question', on_delete=models.CASCADE)

    def __str__(self):
        return "{0}, view: {1}".format(self.answer, self.answer_number)


class Vote(models.Model):
    answer = models.OneToOneField(Answer, related_name="votes", on_delete=models.CASCADE)
    users = models.ManyToManyField(User)

    def __str__(self):
        return str(self.answer.answer)[:30]

在shell我取第一个答案:

>>> Answer.objects.all()[0]
<Answer: choix 1 , view: 0>

我要获取投票对象:

>>> Answer.objects.all()[0].votes
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Hippolyte\AppData\Roaming\Python\Python38\site-packages\django\db\models\fields\related_descriptors.py", line 420, in __get__
    raise self.RelatedObjectDoesNotExist(
questions.models.Answer.votes.RelatedObjectDoesNotExist: Answer has no votes.

但是出现错误。

我不明白为什么 related_name 不被识别。你能帮帮我吗?

您在这里使用了 OneToOneField。因此,这意味着每个 Vote 指向一个 不同的 Anwer 对象。因此,每个 Answer 最多 Vote。像 some_answer.votes 这样的查询将立即查询那个 Vote 对象,如果它不存在,它将引发 RelatedObjectDoesNotExist 错误(这是 ObjectDoesNotExist 异常的子类).所以 related_name 本身被识别了,但是没有相关的 Vote 对象。

然而在这里使用 OneToOneField 是令人惊讶的。意思是每次投票都指向一个唯一的Answer?我想你可能想在这里使用 ForeignKey,否则 related_name='votes' 没有多大意义。

通过不使用 OneToOne 关系查询 Vote 模型来检查您的 Answer 是否有 Vote

尝试做:

ans = Answer.objects.all()[0]
Vote.objects.filter(answer_id = ans.id).all()

额外提示,你应该在related_name上使用单数词(vote而不是votes),因为它是OneToOne,意味着一个Answer只能一个Vote(反之亦然)

您的 related_name 已被识别,但仅当相关对象存在时才分配给实例。

在您的情况下,您的数据库中没有 Vote 实例,其 answer 字段指向您的 Answer 实例

只要捕获异常,return None 如果你想继续:

answer = Answer.objects.all().first()
try:
   vote = answer.votes
except Answer._meta.model.related_field.RelatedObjectDoesNotExist as e:
   vote = None

如果你想缩短它,你可以使用 hasattr(answer, 'vote') 来检查,但这将掩盖所有由数据库查找引起的异常

answer = Answer.objects.all().first()
vote = answer.votes if hasattr(answer, 'votes') else None

请注意,由于您使用了 OneToOneField,如果相关 Vote 存在,answer.votes 将始终 return 单个实例。因此,使用 related_name='vote' (没有 s)

会更合适