我有“发布”对象和“帖子之类”对象,其中有多少人喜欢某个帖子已被哪个用户收到:
class Post(models.Model):
text = models.CharField(max_length=500, default ='')
user = models.ForeignKey(User)
class PostLike(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
我可以选择收到的帖子有多少像这样:
Post.objects.all().annotate(likes=Count('postlike'))
这大致转换为:
SELECT p.*,
Count(l.id) AS likes
FROM post p, postlike l
WHERE p.id = l.post_id
GROUP BY (p.id)
有效。现在,我如何过滤当前用户的Count
聚合?我想要检索不是所有这些帖子的内容,而是所有喜欢的记录用户。生成的SQL应该是:
SELECT p.*,
(SELECT COUNT(*) FROM postlike WHERE postlike.user_id = 1 AND postlike.post_id = p.id) AS likes
FROM post p, postlike l
WHERE p.id = l.post_id
GROUP BY (p.id)
答案 0 :(得分:2)
您知道Count
有一个filter
参数吗?
Post.objects.annotate(
likes=Count('postlike', filter=Q(postlike__user=logged_in_user))
)
答案 1 :(得分:1)
首先尝试添加过滤器:
Post.objects.filter(postlike__user=request.user).annotate(likes=Count('postlike'))
来自docs:
过滤器位于注释之前,因此过滤器会约束计算注释时考虑的对象。
答案 2 :(得分:1)
它并不完全干净,但您可以使用Case
/When
...
posts = Post.objects.all().annotate(likes=models.Count(
models.Case(
models.When(postlike__user_id=user.id, then=1),
default=0,
output_field=models.IntegerField(),
)
))
当然,当你无法通过Django ORM表达某些内容时,你总是可以下载到.extra()
甚至原始SQL。