You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Django ORM为Cafe QuerySet添加统计注解?

Django ORM实现咖啡馆统计数据查询

完全可以通过Django ORM实现这个需求,利用annotate结合聚合函数与条件表达式就能在数据库层面完成统计计算,无需在Python代码中二次处理数据。

实现代码

首先导入所需的ORM工具:

from django.db.models import Count, Case, When, FloatField, F

然后构建QuerySet:

# 获取包含统计字段的咖啡馆查询集
cafes_with_stats = Cafe.objects.annotate(
    # 统计每个咖啡馆的食品总数
    total_foods=Count('foods'),
    # 统计未售食品总数,仅计数状态为NOT_SOLD_OUT的食品
    unsold_foods=Count(
        Case(
            When(foods__status=Food.SoldStatus.NOT_SOLD_OUT, then='foods__id')
        )
    ),
    # 计算未售食品占比,处理无食品时的除数为0问题
    unsold_ratio=Case(
        When(total_foods=0, then=0.0),
        default=F('unsold_foods') / F('total_foods'),
        output_field=FloatField()
    )
)

使用说明

  1. 如果需要字典格式的结果,可在末尾添加.values('name', 'total_foods', 'unsold_foods', 'unsold_ratio'),返回的每条数据就是包含指定字段的字典。
  2. 如果需要保留Cafe模型对象,直接遍历cafes_with_stats即可通过对象属性访问统计字段:
for cafe in cafes_with_stats:
    print(f"咖啡馆:{cafe.name}")
    print(f"食品总数:{cafe.total_foods}")
    print(f"未售食品数:{cafe.unsold_foods}")
    print(f"未售占比:{cafe.unsold_ratio:.2%}\n")

关键逻辑说明

  • Count('foods'):通过外键的related_name直接统计关联的Food数量。
  • Case+When:实现条件过滤,仅对状态为NOT_SOLD_OUT的食品进行计数。
  • F表达式:让数据库层面完成除法计算,避免Python与数据库之间的数据传输,提升效率。
  • 除数为0处理:通过Case判断如果食品总数为0,直接返回0.0,避免出现计算错误。

内容的提问来源于stack exchange,提问作者Jasur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:30:35