多个Django注释计数外键与排除的反向关系返回一个奇怪的结果(18)

时间:2014-10-06 12:57:19

标签: django django-orm

最奇怪的是,要么我错过了一些基本的东西,要么就是django bug

例如:

class Author(Model):
       name = CharField()

class Parent(Model):
       name = CharField(

class Subscription(Model):
      parent = ForeignKey(Parent, related_name='subscriptions')

class Book(Model):
      name = CharField()
      good_book = BooleanField()
      author = ForeignKey(Author, related_name='books')


class AggregatePerson(Model):
     author =  OneToOneField(Author, related_name='+')
     parent =  OneToOneField(Parent, related_name='+')

当我尝试:

AggregatePerson.objects.annotate(counter=Count('author__books')).order_by('counter')

一切正常。如果我添加以下内容,则排序和字段counterexisting_subs会显示正确的数字 BUT

AggregatePerson.objects.annotate(existing_subs=Count('parent__subscriptions')).exclude(existing_subs=0).annotate(counter=Count('author__books')).order_by('counter')

然后counterexisting_subs字段变为 18

为什么18?我做错了什么?

感谢您的帮助!

进一步研究后,

EDIT 澄清:

  1. 是parent__subscriptions的数量,即使没有排除,代码也会中断,**由于某种原因counter也会获得existing_subs
  2. 的值

2 个答案:

答案 0 :(得分:1)

(在另一个论坛上重复我的回复的要点)

这看起来像是一个Django错误。可能的解决方法:

1)在一个annotate()电话中添加两个注释: ...annotate(existing_subs=Count('parent__subscriptions'),counter=Count('author__books'))...

2)用existing_subs替换exclude(existing_subs=0)exclude (parent__subscriptions=None)的注释。

答案 1 :(得分:0)

我找到了这个问题的答案。

铊; DR:

您需要在distinct=True内添加Count ,如下所示:

AggregatePerson.objects.annotate(counter=Count('author__books', distinct=True))

更长的版本:

添加Count注释会在场景后面添加LEFT OUTER JOIN。由于我们添加两个注释,两者都引用同一个表,因为某些行可能出现两次(一次用于第一个注释而另一个用于第二个注释),因此选择和分组行的数量会增加,因为LEFT OUTER JOIN允许空单元格(行) )从右表中选择。