ManyRelatedManager调用在返回至少一个结果时返回空列表

时间:2012-07-31 05:26:54

标签: django django-models

我指定了两个用于跟踪用户对文章实例进行投票的模型(在另一个应用中,在这种情况下为articlescraper)。

from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User)

    articles_upvoted = models.ManyToManyField('useraccounts.UpvotedArticle',
                                              null=True,
                                              blank=True)

class UpvotedArticle(models.Model):
    article = models.ForeignKey('articlescraper.Article')
    user = models.ForeignKey(User)

在Django shell中,我试图通过与UserProfile交互来获取文章列表:

a = UserProfile.objects.get(pk=1)
a.articles_upvoted.all()

返回:

[]

然而,我又走了一步:

b = UpvotedArticle.objects.filter(user=User.objects.get(pk=1))
b

返回:

[<UpvotedArticle: Arch Linux Lexmark S305 Drivers>, <UpvotedArticle: Structure of a Haystack project>]

这是预期的行为,并在UserProfileUpvotedArticle类别的Django管理员中进行镜像。

但是,我不明白为什么尝试获取文章列表无法按照我最初尝试使用a.articles_upvoted.all()的方式进行,如果这两个模型是链接的。

1 个答案:

答案 0 :(得分:2)

因为这些关系并不相同。通过在一侧定义ForeignKey,在另一侧定义ManyToMany,您已经为数据库提供了两个单独的位置来存储有关文章upvoting的信息。

您应该删除ManyToManyField上的UserProfile,并使用自动反向关系:

a = UserProfile.objects.get(pk=1)
a.upvotedarticle_set.all()

或者,您可以将UpvotedArticle识别为ManyToMany关系的“贯穿”表,并在articles_upvoted的定义中明确标记它 - 请注意,该关系应该与{{ 1}},而不是articlescraper.Article

UpvotedArticle

虽然由于你没有在该关系上添加任何额外数据,这是定义显式直通表的常用原因,但您可能希望完全删除它并且只依赖于Django将创建的自动数据。