我有一个非常标准的基本社交应用程序 - 具有状态更新(即帖子)和每个帖子的多个评论。
给定以下简化模型,是否可以使用 Django 的 ORM 高效检索所有帖子以及最新两条评论与每个帖子关联,而不执行 N+1 查询? (也就是说,无需执行单独的查询来获取页面上每个帖子的最新评论。)
class Post(models.Model):
title = models.CharField(max_length=255)
text = models.TextField()
class Comment(models.Model):
text = models.TextField()
post = models.ForeignKey(Post, related_name='comments')
class Meta:
ordering = ['-pk']
Post.objects.prefetch_related('comments').all()
获取所有帖子和评论,但我只想检索每个帖子的有限数量的评论。
UPDATE:
我明白,如果这可以使用 Django 的 ORM 来完成,那么可能必须使用某些版本来完成prefetch_related
。多个查询完全没问题,只要我避免每页进行 N+1 次查询即可。
在 Django 中处理这个问题的典型/推荐方法是什么?
更新2:
似乎没有直接且简单的方法可以通过使用 Django ORM 的简单查询来有效地完成此操作。下面的答案中有许多有用的解决方案/方法/解决方法,包括:
- 在数据库中缓存最新的评论ID
- 执行原始 SQL 查询
- 检索所有评论 ID 并在 python 中进行分组和“加入”
- 限制您的应用程序仅显示最新评论
我不知道应该将哪一个标记为正确,因为我还没有机会尝试所有这些方法,但我向 hynekcer 提供了赏金,因为它提供了多种选择。
更新3:
我最终使用了@user1583799的解决方案。
如果您使用的是 Django 1.7 新版本Prefetch https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related对象(允许您自定义预取查询集)可能会很有帮助。
不幸的是,我想不出一种简单的方法来完全满足您的要求。如果您使用 PostgreSQL 并且愿意只获取每篇文章的最新评论,则以下内容应该适用于两个查询:
comments = Comment.objects.order_by('post_id', '-id').distinct('post_id')
posts = Post.objects.prefetch_related(Prefetch('comments',
queryset=comments,
to_attr='latest_comments'))
for post in posts:
latest_comment = post.latest_comments[0] if post.latest_comments else None
另一种变体:如果您的评论有时间戳,并且您想将评论限制为按日期显示的最新评论,则看起来像:
comments = Comment.objects.filter(timestamp__gt=one_day_ago)
...然后如上所述。当然,您仍然可以对结果列表进行后处理,以将显示限制为最多两条评论。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)