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

如何在Django中通过日期字段获取近6个月月度总费用数据

获取近6个月月度总费用的实现方案

步骤1:计算时间范围

先确定统计的时间区间——近6个月(包含当月),用datetime和python-dateutil的relativedelta精准计算起始日期,确保覆盖完整的6个自然月:

from datetime import datetime
from dateutil.relativedelta import relativedelta

today = datetime.today()
# 取当前月第一天,再往前推5个月,得到6个月前的当月第一天
start_date = (today.replace(day=1) - relativedelta(months=5)).date()

步骤2:ORM分组聚合查询

利用Django ORM的筛选、分组和聚合功能,按年月分组计算每个月的总费用:

from django.db.models import Sum, F
from .models import Visits

# 筛选时间范围内的数据,按年、月分组并统计总费用
monthly_data = Visits.objects.filter(
    visit_date__gte=start_date
).annotate(
    year=F('visit_date__year'),
    month=F('visit_date__month')
).values('year', 'month').annotate(
    total_fees=Sum('fees')
).order_by('-year', '-month')

按year和month分组是为了避免跨年的同名月份(如2023年7月和2024年7月)被混淆。

步骤3:转换为目标格式

将查询结果转换成以月份名称为键的字典,借助calendar模块获取月份名称:

import calendar

# 基础转换(仅包含有数据的月份)
result = {}
for item in monthly_data:
    month_name = calendar.month_name[item['month']]
    result[month_name] = item['total_fees']

可选:补全无数据的月份

如果需要即使某个月份没有访问记录,也显示总费用为0,可以先生成近6个月的完整月份列表,再填充数据:

# 生成近6个月的年、月列表(按从新到旧排序)
months_list = []
current_year, current_month = today.year, today.month
for i in range(6):
    calc_month = current_month - i
    calc_year = current_year
    if calc_month <= 0:
        calc_month += 12
        calc_year -= 1
    months_list.append((calc_year, calc_month))

# 初始化所有月份总费用为0
full_result = {calendar.month_name[m[1]]: 0 for m in months_list}

# 填充已有数据
for item in monthly_data:
    month_name = calendar.month_name[item['month']]
    full_result[month_name] = item['total_fees']

# 保持月份从新到旧的顺序
ordered_result = {}
for year, month in months_list:
    ordered_result[calendar.month_name[month]] = full_result[calendar.month_name[month]]

最终效果

运行后ordered_result会输出类似需求的格式:

{
    'July': Decimal('750.00'),
    'June': Decimal('800.00'),
    'May': Decimal('500.00'),
    'April': Decimal('200.00'),
    'March': Decimal('450.00'),
    'February': Decimal('310.00')
}

注:fees是DecimalField类型,结果会是Decimal对象,若需要转成整数可使用int(item['total_fees'])(前提是费用均为整数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:57:17