Python Django中如何按月份对DateField获取去重查询集?
针对Django模型按月份过滤及去重查询集的实现方案
嘿,作为Django新手能想到按月份过滤和去重的需求,已经很到位啦!Django ORM本身就提供了现成的方法来实现你的需求,不用自己写复杂的SQL,下面给你详细拆解:
一、按月份过滤查询集
要针对date字段按月份过滤,直接用Django ORM的**字段查找(Field Lookups)**功能里的__month即可:
# 过滤出所有10月份的记录 october_records = MyModel.objects.filter(date__month=10)
不过要注意,如果你的数据跨了多个年份,上面的写法会把所有年份的10月份记录都查出来。如果需要精确到「某年某月」,可以结合__year一起过滤:
# 过滤出2024年10月份的记录 october_2024_records = MyModel.objects.filter(date__year=2024, date__month=10)
二、获取按月份去重的查询集
如果要获取所有唯一的月份(准确说是唯一的「年月」组合,避免不同年份的同月份重复),可以用Django的数据库函数来截断日期或提取年月,再结合values()和distinct()实现:
方法1:用TruncMonth截断日期到月份(推荐)
TruncMonth是Django 1.10+引入的函数,它会把日期截断到当月的第一天(比如2024-10-15会变成2024-10-01),之后我们基于这个截断后的日期去重:
from django.db.models.functions import TruncMonth # 获取所有唯一的年月,返回字典列表,每个字典包含'truncated_date'键(值为当月第一天) unique_months = MyModel.objects.annotate( truncated_date=TruncMonth('date') ).values('truncated_date').distinct().order_by('truncated_date')
order_by('truncated_date')是为了让结果按时间顺序排列,方便查看。
方法2:提取年份和月份字段
如果你的Django版本较低(低于1.10),可以用ExtractYear和ExtractMonth分别提取年份和月份,再基于这两个字段去重:
from django.db.models.functions import ExtractYear, ExtractMonth # 获取所有唯一的年月组合,返回字典列表,包含'year'和'month'键 unique_month_years = MyModel.objects.annotate( year=ExtractYear('date'), month=ExtractMonth('date') ).values('year', 'month').distinct().order_by('year', 'month')
进阶:同时获取月份的统计数据
如果除了去重的月份,你还想得到每个月的汇总数据(比如总金额、记录数),可以在annotate之后再添加聚合函数:
from django.db.models import Sum, Count from django.db.models.functions import TruncMonth monthly_summary = MyModel.objects.annotate( month=TruncMonth('date') ).values('month').annotate( total_amount=Sum('amount'), # 当月总金额 record_count=Count('id') # 当月记录条数 ).order_by('month')
这样返回的结果里,每个条目都会包含对应的月份、总金额和记录数,非常实用~
内容的提问来源于stack exchange,提问作者SEJ
相关产品推荐
相关产品推荐

