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

如何在Django查询中计算距截止日期剩余天数?遇Case报错求解

问题解决方案

错误原因及修复步骤

  1. Case() got an unexpected keyword argument 'default'
    Django的Case表达式不支持default参数,对应的默认分支参数是otherwise,替换即可。

  2. TypeError: QuerySet.annotate() received non-expression(s):
    你用Value()包裹了F()表达式的计算结果,这是错误的。F()本身就是数据库可识别的表达式,无需用Value()包装——Value()仅用于包裹常量值(如数字、字符串)。

修正后的代码

方案1:返回天数差(timedelta类型)

from django.db.models import Case, When, F, Value, DurationField
from django.db.models.functions import TruncDate, Now

query_list = file.qs.annotate(
    overdue=Case(
        # 截止日期晚于当前日期,计算剩余时间差
        When(due_date__gt=TruncDate(Now()), then=F('due_date') - TruncDate(Now())),
        # 截止日期为空,返回None
        When(due_date__isnull=True, then=Value(None)),
        # 其他情况(已逾期或当天到期)返回0
        otherwise=Value(0),
        output_field=DurationField()
    )
).values_list('overdue', ...)

方案2:返回整数天数

如果需要直接得到剩余天数的整数而非时间间隔对象,可以使用ExtractDay函数:

from django.db.models import Case, When, F, Value, IntegerField
from django.db.models.functions import TruncDate, Now, ExtractDay

query_list = file.qs.annotate(
    overdue_days=Case(
        When(due_date__gt=TruncDate(Now()), then=ExtractDay(F('due_date') - TruncDate(Now()))),
        When(due_date__isnull=True, then=Value(None)),
        otherwise=Value(0),
        output_field=IntegerField()
    )
).values_list('overdue_days', ...)

额外说明

  • 使用TruncDate(Now())替代timezone.now().date():确保使用数据库服务器的当前日期,避免Python运行环境与数据库的时间差问题。
  • 若due_date是DateTimeField,TruncDate会自动提取日期部分进行比较,结果更准确。
  • 如果不想返回None,可以用Value(-1)等特殊值标记due_date为空的情况,避免可能的类型兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:24:27