python - 如何在 Django 中过滤对象以进行计数注释?

标签 python django django-models django-aggregation

考虑简单的 Django 模型 EventParticipant:

class Event(models.Model):
    title = models.CharField(max_length=100)

class Participant(models.Model):
    event = models.ForeignKey(Event, db_index=True)
    is_paid = models.BooleanField(default=False, db_index=True)

使用参与者总数注释事件查询很容易:

events = Event.objects.all().annotate(participants=models.Count('participant'))

如何用 is_paid=True 过滤的参与者数量进行注释?

无论参与者有多少,我都需要查询所有事件,例如我不需要按带注释的结果进行过滤。如果有 0 个参与者,那没关系,我只需要 0 在注释值中。

example from documentation在这里不起作用,因为它从查询中排除对象,而不是用 0 注释它们。

更新。 Django 1.8 有新的 conditional expressions feature ,所以现在我们可以这样做:

events = Event.objects.all().annotate(paid_participants=models.Sum(
    models.Case(
        models.When(participant__is_paid=True, then=1),
        default=0,
        output_field=models.IntegerField()
    )))

更新 2。 Django 2.0 有新的 Conditional aggregation功能,见 the accepted answer以下。这也适用于 Django 3.x

最佳答案

Conditional aggregation在 Django 2.0 中,您可以进一步减少过去的 faff 数量。这也将使用 Postgres 的 filter 逻辑,这比 sum-case 快一些(我见过像 20-30% 这样的数字)。

无论如何,在你的情况下,我们正在研究这样简单的事情:

from django.db.models import Q, Count
events = Event.objects.annotate(
    paid_participants=Count('participants', filter=Q(participants__is_paid=True))
)

文档中有一个单独的部分关于 filtering on annotations .它与条件聚合相同,但更像我上面的示例。不管怎样,这比我之前做的那些粗糙的子查询要健康得多。

关于python - 如何在 Django 中过滤对象以进行计数注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30752268/

相关文章:

Python 类利用 Turtle 对象在 Windows 上不工作,在 Linux 上工作

python - 在 PythonAnywhere 中使用 Virtualenv 时错误的 Python 版本

python - django View 中的原始 SQL 显示错误

Django 过滤查询在大行数据集上速度缓慢

python - Django)属性错误: 'datetime.date' object when trying to get an object of model

python - 您如何使用 Selenium 检查属性是否存在并获取其值(如果存在)?

python - 网页抓取到 .csv

c# - 如何使套接字客户端准备好发送和接收而不需要服务器的操作?

python - 最新的 django-mongodb-engine

django - 找不到页面 (404) Django : 错误