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

Django按预约开始日计算用户年龄筛选ReservationFrame出现TypeError

错误原因

你代码中的比较逻辑(ExtractMonth('start_at'), ExtractDay('start_at')) < (person_birthday.month, person_birthday.day)是在Python运行时直接执行的,左侧是Django ORM的查询表达式对象,右侧是整数类型,二者不支持直接在Python层做比较,需要将比较逻辑转换为数据库可识别的ORM查询条件。

解决方案

将生日未过的判断逻辑拆分为两个可在数据库层执行的条件:

  • 预约开始月份 < 用户生日月份
  • 预约开始月份等于用户生日月份,且预约开始日期 < 用户生日日期
    满足任一条件时年龄计算额外减1即可。

另外需要注意JSON字段的数值比较问题:如果使用PostgreSQL作为数据库,JSON字段内的数值默认以字符串类型返回,比较时需要添加__int后缀强制转为整数再比较;如果使用MySQL作为数据库,直接使用原字段名比较即可。

完整可运行代码

from django.db.models import F, Case, When, IntegerField, Q
from django.db.models.functions import ExtractYear

# 提前取出用户生日的年月日三个字段,避免重复访问属性
person_birthday = request.user.person.birthday
birth_year = person_birthday.year
birth_month = person_birthday.month
birth_day = person_birthday.day

reservation_frames = reservation_frames.annotate(
    age=ExtractYear('start_at') - birth_year - Case(
        When(
            Q(start_at__month__lt=birth_month) | Q(start_at__month=birth_month, start_at__day__lt=birth_day),
            then=1
        ),
        default=0,
        output_field=IntegerField()
    )
)

# 过滤下限:无下限 或 年龄≥下限
reservation_frames = reservation_frames.filter(
    Q(information__has_key='lower_age_limit') == False |
    Q(information__lower_age_limit__int__lte=F('age'))
)

# 过滤上限:无上限 或 年龄≤上限
reservation_frames = reservation_frames.filter(
    Q(information__has_key='upper_age_limit') == False |
    Q(information__upper_age_limit__int__gte=F('age'))
)

补充说明

你代码中定义的frames_without_age_limit变量未被使用,如果需要单独获取无年龄限制的记录可以单独使用这个变量,否则可以删除该行。如果不需要保留年龄计算字段用于后续逻辑,也可以提前将年龄判断逻辑直接写在过滤条件中,无需annotate即可直接过滤,查询性能更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 23:54:02