无法按created_date筛选Django模型数据,图表无数据请求排查
问题排查与解决方案
我来帮你梳理下问题的核心原因,以及对应的修复方案:
核心问题:Datetime字段与Date对象的匹配冲突
你的created_dates是datetime类型字段(存储了完整的年月日时分秒,比如2020-10-19 09:39:19.894184),但你用纯date对象(比如2020-10-19)去做精确匹配,数据库里没有任何一条记录的created_dates会完全等于这个不带时分秒的date值,所以返回空QuerySet是必然结果。
你之前尝试的__gte=startdate/__lte=enddate如果用的是date对象,也会因为同样的逻辑出错:比如created_dates__lte=days会被解析为<= 2020-10-19 00:00:00,自然找不到当天非零点的记录。
修复方案(三种可选,按简洁度排序)
方案1:使用Django内置的__date查询条件(最推荐)
Django提供了__date查询后缀,可以直接提取datetime字段的日期部分进行匹配,忽略时分秒:
from datetime import date, timedelta import datetime from django.shortcuts import render from .models import Products # 确保导入你的模型 def data_chart(request): data = [] # 注意:range(0,7)才是包含今天的近7天,原代码range(1,7)只取了前6天 week_days = [datetime.datetime.now().date() - timedelta(days=i) for i in range(0,7)] for days in week_days: # 用__date匹配当天所有datetime记录 product_count = Products.objects.filter(created_dates__date=days).count() date_str = days.strftime("%d.%m") item = {"day": date_str,"value": product_count} data.append(item) # 可选:反转数据让日期从旧到新排列,更符合图表展示逻辑 data.reverse() return render(request, 'chartpage.html', {'data': data})
方案2:构造当天的完整时间范围
手动构造某一天的起始(00:00:00)和结束(23:59:59)datetime,用__range匹配:
# 在循环内替换filter部分 start_of_day = datetime.datetime.combine(days, datetime.time.min) end_of_day = datetime.datetime.combine(days, datetime.time.max) product_count = Products.objects.filter(created_dates__range=(start_of_day, end_of_day)).count()
方案3:批量查询优化(减少数据库请求次数)
如果数据量较大,推荐一次性查询近7天的所有统计数据,避免循环执行7次数据库查询:
from datetime import date, timedelta import datetime from django.shortcuts import render from django.db.models import Count from django.db.models.functions import TruncDate from .models import Products def data_chart(request): end_date = datetime.datetime.now().date() start_date = end_date - timedelta(days=6) # 一次性查询近7天每天的记录数 daily_counts = Products.objects.filter( created_dates__date__gte=start_date, created_dates__date__lte=end_date ).annotate( day=TruncDate('created_dates') # 提取日期部分 ).values('day').annotate( count=Count('id') # 按日期分组计数 ).order_by('day') # 补全没有数据的日期(避免某天无数据就缺失条目) date_range = [start_date + timedelta(days=i) for i in range(7)] count_map = {item['day']: item['count'] for item in daily_counts} data = [] for day in date_range: data.append({ "day": day.strftime("%d.%m"), "value": count_map.get(day, 0) }) return render(request, 'chartpage.html', {'data': data})
额外优化提示
- 用
count()代替len(queryset):count()是在数据库层面完成计数,不需要把所有记录加载到内存,效率更高。 - 确认日期范围:原代码的
range(1,7)只覆盖了前6天,如果你需要包含今天的近7天,一定要改成range(0,7)。
内容的提问来源于stack exchange,提问作者Murat Demir
相关产品推荐
相关产品推荐

