Django:如何为每个外键选择有限数量的行?

Gab*_*iMe 5 django

class Comment (models.Model):
        user = models.ForeignKey(User, related_name="comments")
        title = models.TextField(max_length=256)
        comment = models.TextField(max_length=1286)
        created = models.DateTimeField(db_index=True)
Run Code Online (Sandbox Code Playgroud)

现在我如何获得最新评论,但仅将结果限制为每个同一用户的评论(例如3)?

以下是它在纯SQL中的完成方式:如何为每个外键选择有限数量的行?

Ant*_*off 3

我想,这会起作用:

Comment.objects.filter(*[
    ~Q(id__in=user.comments.order_by('-created')[3:].values_list('id', flat=True))
    for user in User.objects.all()
])
Run Code Online (Sandbox Code Playgroud)

然而,这似乎既不是Python式的,也不是解决问题的有效方法。(使用缓存可以在一定程度上解决效率问题,但仍然如此。)

无论如何,你想达到什么目的?您可以只获取所有用户的评论并仅使用最新的三个。假设您的评论按-created字段排序:

{% for user in users %}
    {% for comment in user.comments.all|slice:"3" %}{{ comment }}{% endfor %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

切片将转换为LIMITSQL 查询中的子句,因此您无论如何都不会获得所有注释。当然,会执行多个查询来获取所有评论,因此使用模板缓存会有所帮助。

同样,这对于您的情况可能没有意义。如果没有,最好澄清一下要求。

原始SQL

如果您知道如何使用原始 SQL 执行您想要的操作([1] 可能有帮助),那么您需要找到一种方法将其放入extra()某种方式中([2] 是复杂的额外查询的示例,它可能会给您一个想法)。

[1]如何为每个外键选择有限数量的行?

[2] django 的 .extra(where= 子句被表重命名 .filter(foo__in=... subselects 破坏)