假设我有以下型号:添加额外的多对多领域Django的查询集
class Thing(models.Model):
name = models.CharField(max_length=100)
ratings = models.ManyToManyField('auth.User', through='Rating')
class Rating(models.Model):
user = models.ForeignKey('auth.User')
thing = models.ForeignKey('Thing')
rating = models.IntegerField()
所以我有很多事情,每个用户可以给每一个事情。我也有一个视图,显示所有事物的列表(并且它们数量巨大),用户分配给他们每个人的评分。我需要一种方法来检索数据库中的所有数据:带有额外字段user_rating
的事物最多取自一个(因为我们有固定用户)相关评级对象。
平凡解看起来像这样:
things = Thing.objects.all()
for thing in things:
try:
thing.user_rating = thing.ratings.objects.get(user=request.user).rating
except Rating.DoesNotExist:
thing.user_rating = None
但是,这种方法的缺陷是显而易见的:如果我们有500分的事情,我们会做501个请求数据库。每页。每个用户。这是该网站浏览次数最多的页面。这个任务很容易用SQL JOIN解决,但实际上我有更复杂的模式,我肯定会受益于Django模型框架。所以问题是:是否可以这样做Django方式?如果不是,考虑到这些任务非常普遍,这将是非常奇怪的。
据我所知,annotate()
或select_related()
都不会帮助我。
您仍然得到每个用户的查询,而不是聚合。 – Tom 2012-01-06 17:33:58
好的,但它绝对不是完美的。如果事情分成页面怎么办?比如说,有10000个东西,页面包含100个条目。第二个循环将不得不查看所有可能的10000个评分。 – user285176 2012-01-06 19:03:10
@Tom至少有2个查询,而不是n + 1 – user285176 2012-01-06 19:05:18