仅过滤Django中的Annotations

Col*_*son 19 django orm

以以下示例为例:http: //docs.djangoproject.com/en/dev/topics/db/aggregation/#filter-and-exclude

Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))
Run Code Online (Sandbox Code Playgroud)

反正有没有过滤器只适用于注释,所以它会返回所有发布者,有些具有num_books = 0?

cza*_*aic 23

您可以在过滤器中使用注释变量.

publishers=Publisher.objects.annotate(num_books=Count('book')).filter(num_books__gte=2)
Run Code Online (Sandbox Code Playgroud)


Mac*_*sch 11

嗯,我想你必须使用一个额外的条款:

Publisher.objects.extra(select={
    'num_books': 'SELECT COUNT(*) ' + \
                 'FROM <your_app>_book ' + \
                 'WHERE <your_app>_book.publisher_id = ' + \
                       '<your_app>_publisher.id AND ' + \
                       'rating > 3.0'
})
Run Code Online (Sandbox Code Playgroud)

  • @NathanTregillus它不会创建任何其他查询,因为它都是在SQL中完成的.它会慢一点,因为查询更复杂,但没有像每个对象的一个​​查询. (2认同)

thi*_*er3 6

from django.db import models

Publisher.objects.annotate(
    num_books=models.Sum(
        models.Case(
            models.When(
                book__rating__gt=3.0,
                then=1,
            ),
            default=0,
            output_field=models.IntegerField(),
        )
    )
).filter(
    num_books=0,
)
Run Code Online (Sandbox Code Playgroud)


iva*_*nys 5

从 Django 2.0 开始可以使用filter聚合函数的参数:

from django.db.models import Q    
Publisher.objects.annotate(num_books=Count('book', filter=Q(book__rating__gt=3.0)))
Run Code Online (Sandbox Code Playgroud)

答案基于备忘单