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

无法按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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:17:50