Django如何按币种规则实现Permit模型按月汇总求和的ORM查询
实现方案
你可以使用Django的Case/When条件表达式一次性完成所有币种的计算和月度汇总,不需要拆分两次查询,逻辑和你模型中定义的euro_value属性完全对齐,性能也更好。
第一步:导入依赖包
from django.db.models import Case, When, F, Sum, DecimalField from django.db.models.functions import Round import calendar
如果你的Django版本低于3.2,没有内置Round函数,可以跳过导入,最后格式化数据时再做四舍五入处理。
第二步:执行统计查询
# 替换为你实际需要查询的年份 target_year = 2024 monthly_total = Permit.objects.filter( info__date_of_transaction__year=target_year, # 过滤空值避免计算错误 volume__isnull=False, unit_price__isnull=False, ex_rate__isnull=False ).annotate( # 按币种规则计算单条记录的欧元价值,保留两位小数 euro_value = Round( Case( When(currency='USD', then=F('volume') * F('unit_price') / F('ex_rate')), default=F('volume') * F('unit_price') * F('ex_rate'), output_field=DecimalField() ), 2 ) ).values( 'info__date_of_transaction__month' ).annotate( total = Sum('euro_value') ).order_by('info__date_of_transaction__month')
第三步:转换为期望的输出格式
labels = [] data = [] for item in monthly_total: # 把月份数字转为英文名称 labels.append(calendar.month_name[item['info__date_of_transaction__month']]) # 数值转为两位小数字符串 data.append(f"{item['total']:.2f}") result = {"labels": labels, "data": data}
如果没有使用Round函数,把数值格式化的行替换为以下代码即可:
data.append(f"{round(item['total'], 2):.2f}")
内容的提问来源于stack exchange,提问作者Oppong Ntiamoah
相关产品推荐
相关产品推荐

