假设我有以下模型:
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()
都无法帮助我。
答案 0 :(得分:3)
我想你应该试试这个: https://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra
实施例
result = Thing.objects.all().extra(select={'rating': 'select rating from ratings where thing_id = id'})
您的结果集会为每个“事物”对象获取一个新字段“评级”。
我在最近的一个项目中使用这种方法。它生成一个复杂的查询而不是n + 1个查询。
希望这会有所帮助:)
答案 1 :(得分:0)
因为您计划在一个页面中显示所有内容。我能想到这种方法。你可以尝试一下:
获取当前用户提供的所有评分并获取所有内容。
现在尝试创建一个这样的字典:
thing_dict = {}
for thing in Thing.objects.all():
thing_dict[thing] = None
for rating in Rating.objects.filter(user = request.user):
thing_dict[rating.thing] = rating
现在,thing_dict包含模型Thing作为键的所有条目,并将其评级作为其值。
可能不是最好的方法。我很想知道其他人的回答。