【问题标题】:Filtering within an annotate() query在 annotate() 查询中过滤
【发布时间】:2012-01-23 03:56:01
【问题描述】:

我正在制作一个带有 cmets 的 django 应用程序,并以 stackoverflow 或 reddit 风格对这些 cmets 进行投票。选择 cmets 时,我想知道总投票数,以及用户是否对这个特定评论进行了投票。我可以像这样使用 annotate 来计算总计数:

video_comments = Comment.objects.filter(video_id=video_id).annotate(vote_sum=Sum('commentvote__value'))

我还可以对部分评论投票进行注释吗?比如:

.annotate(user_vote=Sum('commentvote__value').filter(commentvote__user == user))

作为参考,这是我的模型:

class Comment(models.Model):
    video_id = models.CharField(max_length=12, db_index=True)
    video_time = models.FloatField()

    comment = models.TextField(max_length=MAX_COMMENT_LENGTH)

    datetime = models.DateTimeField(auto_now_add = True)
    user = models.ForeignKey(User)

class CommentVote(models.Model):
    comment = models.ForeignKey(Comment, db_index=True)
    value = models.IntegerField() # Should be 1 or -1

    datetime = models.DateTimeField(auto_now_add = True)
    user = models.ForeignKey(User, db_index=True)

【问题讨论】:

  • 您可能希望将unique_together = ('comment', 'user') 添加到CommentVote。此外,在 MySQL 和 PostgreSQL 中,ForeignKeys 上的 db_index 不是必需的。
  • 谢谢托马斯!我错过了 unique_together。

标签: django django-models django-queryset


【解决方案1】:

根据this,您可以在注释之前过滤给定的字段:

Comment.objects.filter(video_id=video_id).filter(commentvote__user=user))\
               .annotate(user_vote=Sum('commentvote__value'))

不幸的是,这将评论集范围缩小到只有那些有给定用户投票的 cmets。但是你也可以得到剩余的cmets:

Comment.objects.filter(video_id=video_id).exclude(commentvote__user=user))

并手动合并两个列表。

【讨论】:

  • 顺便说一句,这现在也正是 OP 所需要的,但我不能在同一个相关模型上同时进行两个注释,如果一个是“全局”而第二个是过滤的..
  • 啊,上面评论中的“现在”应该是“不”
【解决方案2】:

我认为这应该可以满足您的要求:

CommentVote.objects.values('comment').filter(comment__video_id=video_id,user=user).annotate(vote_sum=Sum('value')).values_list('comment','vote_sum',)

【讨论】:

  • 我能知道我在这个答案中犯的错误吗?
  • 据我所知,它只是没有做你宣传它应该做的事情。但如果你证明它有效,那么我很乐意推翻投票。
  • 嘿 Tomasz,我发现了一个可能的错误。过滤器应该放在注释之前。还有错误吗?
  • 您的查询现在相当于:CommentVote.objects.filter(user=user, comment__video_id=video_id).values_list('comment', 'value'),即过滤给定用户的投票给定视频并为他们返回comment_idvalue(伪装成vote_sum)。
  • 我认为(并且它也有效)annotate 将基于values('comment')particular video_id and user 工作。 values_list 是这个过程中的下一个。如果我在任何地方错了,请纠正我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2015-10-17
  • 2018-08-09
  • 1970-01-01
  • 2022-06-12
相关资源
最近更新 更多