【问题标题】:Django: problem with merging querysets after annotationDjango:注释后合并查询集的问题
【发布时间】:2011-01-25 15:45:05
【问题描述】:

我有一个“对话”经理,看起来像这样:

class AnnotationManager(models.Manager):
def get_query_set(self):
    return super(AnnotationManager, self).get_query_set().annotate(
        num_votes=Count('vote', distinct=True),
        num_comments=Count('comment', distinct=True),
        num_commentators = Count('comment__user', distinct=True),
    )

Votes and Comments 有一个外键到对话框。评论对用户有一个外键。当我这样做时:

dialogs_queryset = Dialog.public.filter(organization=organization)
dialogs_popularity = dialogs_queryset.exclude(num_comments=0) | dialogs_queryset.exclude(num_votes=0)

...dialogs_popularity 永远不会返回组合,而只会返回超过 0 cmets 的对话框,或者如果我更改 OR 的顺序,则返回超过 0 票的对话框!

对我来说,预期的行为是获得超过 0 票的对话和超过 0 cmets 的对话。

我错过了什么?还是这里的注释行为有错误?

【问题讨论】:

    标签: django annotations django-queryset annotate


    【解决方案1】:

    想要带有投票和 cmets 的对话框吗?

    # must have both a vote and a comment
    # aka.  has_comments_and_votes = has_comments AND has_votes
    #                              = !(has_no_comments OR has_no_votes)
    has_comments = ~Q(num_comments=0)
    has_votes = ~Q(num_votes=0)
    
    dialogs_queryset.filter(num_comments__ne=0, num_votes__ne=0)
    # or with Q objects
    dialogs_queryset.filter(has_comments & has_votes)
    dialogs_queryset.exclude(~has_comments | ~has_votes)
    

    或具有投票、cmets 或两者的对话。 (根据评论您想要什么。)

    # must have at least 1 vote or 1 comment
    # aka. has_comments_or_votes = has_comments OR has_votes
    #                            = !(has_no_comments AND has_no_votes)
    dialogs_queryset.exclude(num_comments=0, num_votes=0)
    # again with Q objects
    dialogs_queryset.filter(has_comments | has_votes)  # easiest to read!
    dialogs_queryset.exclude(~has_comments & ~has_votes)
    

    我添加了Q objects 示例,因为“|”在您的代码示例中似乎暗示了它们,它们使创建 ORed 查询变得更加容易。

    编辑: 我添加了has_commentshas_votes 以使内容更易于阅读。

    【讨论】:

    • 看来您已经颠倒了代码块及其描述。
    • 我在每个代码块的描述中添加了更多内容。请再看一下,并提供有关如何反转描述的更明确的详细信息。谢谢。
    • 谢谢。为了清楚起见,我正在寻找具有投票、cmets 或两者兼而有之的对话框。我尝试了您的代码,但仍然无法正常工作。 dialogs_queryset.filter(num_cmets__ne=0, num_votes__ne=0) ...给我没有投票和没有 cmets 的对话框。 dialogs_queryset.exclude(num_cmets=0, num_votes=0) ...给我与 cmets AND 投票的对话。当我对带注释的值执行此操作时,代码的行为方式与我期望的不同!
    • 这个: dialogs_popularity = dialogs_queryset.filter(Q(num_cmets=0) & Q(num_votes=0)) ... 给出与完全相同的结果相同的结果,但将过滤器替换为排除。真的很奇怪吗?
    • 我现在设法编写了两行代码来解决这个问题,但感觉就像一个奇怪的方法! q1 = dialogs_queryset.exclude(Q(num_cmets=0) | Q(num_votes=0)) dialogs_popularity = dialogs_queryset |第一季度
    猜你喜欢
    • 2018-01-17
    • 1970-01-01
    • 2020-05-14
    • 2018-02-06
    • 2020-05-23
    • 1970-01-01
    • 2018-06-19
    • 2013-03-19
    • 1970-01-01
    相关资源
    最近更新 更多