Django2使用聚合Sum跨表查询2020年节日关联的game类支出总金额
原查询返回None的核心原因
- 语法括号错位:原代码中
filter(Fastivalname__startswith=2020.values('id')[0]['id']没有正确闭合子查询的括号,导致values()被当作了startswith的参数值,整个子查询逻辑完全失效,匹配不到有效ID - 字段类型不匹配:
Fastivalname是字符串类型字段,startswith筛选需要传入字符串'2020',传入整数2020无法匹配表A中存储的节日名内容 - 筛选逻辑漏数据:原代码只取了第一个匹配2020开头的节日ID,没有覆盖所有符合前缀的节日记录,即使语法正确也会漏算2020Thanksgiving对应的支出
- 聚合取值键错误:Django的
aggregate(Sum('money'))如果不指定自定义别名,返回的字典默认键为money__sum,直接取['money']自然会拿到None
正确实现方案
依托Django ORM的跨表查询能力,不需要手动拆分两次查表,直接通过双下划线关联外键字段即可完成筛选,有两种常用实现方式:
写法1:直接跨表聚合(最简洁)
from django.db.models import Sum context["money"] = TableB.objects.filter( # 跨表关联TableA筛选名称以2020开头的节日 fastival_name__Fastivalname__startswith='2020', useofmoney='game' ).aggregate( total_money=Sum('money') )['total_money'] or 0
说明:最后加
or 0是为了匹配不到记录时返回0,避免None值影响前端逻辑。按你提供的示例数据,该查询会匹配到两笔符合要求的支出:2020Xmas关联的100元游戏支出、2020Thanksgiving关联的15元游戏支出,最终返回总和115。
写法2:先筛符合条件的节日ID再聚合(适合复杂场景)
如果后续节日的筛选逻辑变复杂,可以先单独查出所有符合要求的节日ID列表,再匹配表B的记录,逻辑可读性更强:
from django.db.models import Sum # 查询所有名称以2020开头的节日ID列表 target_festival_ids = TableA.objects.filter( Fastivalname__startswith='2020' ).values_list('id', flat=True) context["money"] = TableB.objects.filter( fastival_name_id__in=target_festival_ids, useofmoney='game' ).aggregate( total_money=Sum('money') )['total_money'] or 0
注意事项
- 跨表筛选时的字段名要和模型定义完全一致:正向外键查询关联表字段时,前缀用模型里定义的外键名
fastival_name,不要直接用数据库层面的字段名fastival_name_id - 模型里定义的
related_name="TableA_Fastival_name"仅用于从TableA反向查询关联的TableB数据,不影响正向跨表筛选的写法
内容的提问来源于stack exchange,提问作者ChrisChan
相关产品推荐
相关产品推荐

