Django中使用values()按月份分组统计分类金额总和的问题
按分类+月份统计金额总和的Django实现方法
1. 数据库层面分组统计
首先用Django的TruncMonth函数提取日期的年月信息(避免跨年度同月份混淆),结合Sum函数按分类和月份分组统计。
先导入必要模块:
from django.db.models import Sum from django.db.models.functions import TruncMonth
执行查询语句:
query_result = model.objects.values( 'category', month=TruncMonth('date') # 提取当月第一天的datetime对象,包含完整年月 ).annotate( total_amount=Sum('amount') ).order_by('category', 'month')
查询结果为字典列表,每条数据对应一个分类某一月的总金额:
[ {'category': 'A', 'month': datetime.date(2024, 1, 1), 'total_amount': 100}, {'category': 'A', 'month': datetime.date(2024, 2, 1), 'total_amount': 180}, {'category': 'B', 'month': datetime.date(2024, 1, 1), 'total_amount': 150}, {'category': 'B', 'month': datetime.date(2024, 2, 1), 'total_amount': 200}, ]
2. 转换为嵌套字典格式
在视图中将查询结果整理成你需要的嵌套结构,同时收集所有月份用于表头展示:
from collections import defaultdict category_month_totals = defaultdict(dict) all_months = set() for item in query_result: category = item['category'] # 将月份格式化为易读的字符串,比如"2024-01" month_str = item['month'].strftime('%Y-%m') category_month_totals[category][month_str] = item['total_amount'] all_months.add(month_str) # 对月份排序,保证展示顺序正确 sorted_months = sorted(all_months)
处理后得到的category_month_totals即为目标格式:
{ 'A': {'2024-01': 100, '2024-02': 180}, 'B': {'2024-01': 150, '2024-02': 200} }
3. 模板渲染表格
将category_month_totals和sorted_months传入模板后,按以下步骤渲染表格:
自定义模板过滤器
在app的templatetags目录下创建custom_filters.py,用于从字典中取值:
from django import template register = template.Library() @register.filter def get(dictionary, key): return dictionary.get(key)
模板代码
加载过滤器并渲染表格:
{% load custom_filters %} <table border="1"> <thead> <tr> <th>Category</th> {% for month in sorted_months %} <th>{{ month }}</th> {% endfor %} </tr> </thead> <tbody> {% for category, month_totals in category_month_totals.items %} <tr> <td>{{ category }}</td> {% for month in sorted_months %} <!-- 无数据的月份显示0 --> <td>{{ month_totals|get:month|default:0 }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table>
内容的提问来源于stack exchange,提问作者Sapna Sharma
相关产品推荐
相关产品推荐

