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

Django中DateTimeField改为DateField后查询历史数据报错如何解决?

问题触发原因

这个问题本质是SQLite弱类型特性+Django默认迁移逻辑不完善共同导致的:

  1. 你原来的start_date、end_date是DateTimeField,SQLite中存储的是完整的带时间的字符串格式,比如2021-11-30 11:41:29
  2. 直接执行AlterField把字段类型改成DateField时,Django只会修改表结构的字段类型声明,不会主动转换已有数据的存储格式,原有带时间的字符串不会被截断为纯日期格式
  3. 当查询数据时,Django会按DateField的规则解析值,用-分割字符串后取三段转整数生成日期对象,此时最后一段会变成31 11:41:29,转int时报错。

如果是MySQL、PostgreSQL这类强类型数据库,改字段类型时会自动截断时间部分保留日期,不会出现这个问题,仅SQLite场景会触发。

修复方案

分两种场景处理:

场景1:错误迁移还未在生产环境执行

先回退本地迁移、删除错误的迁移文件,按三步安全修改字段类型:

  1. 给FacilityTender模型新增两个临时DateField字段,设置null=True:
start_date_new = models.DateField(null=True)
end_date_new = models.DateField(null=True)
  1. 生成迁移并执行,再新建一个数据迁移,把原有DateTimeField的日期部分赋值给新字段:
# 数据迁移的operations里添加
migrations.RunPython(lambda apps, schema_editor: (
    FacilityTender := apps.get_model('company', 'FacilityTender'),
    [setattr(obj, 'start_date_new', obj.start_date.date()) or setattr(obj, 'end_date_new', obj.end_date.date()) or obj.save() for obj in FacilityTender.objects.all()]
))
  1. 删除原有start_date、end_date字段,把start_date_new、end_date_new重命名为start_date、end_date,再生成迁移执行即可。

场景2:错误迁移已经在生产环境执行

直接写SQL修正现有存储的字段值,新建一个空白迁移,添加如下操作:

migrations.RunSQL(
    "UPDATE company_facilitytender SET start_date = DATE(start_date), end_date = DATE(end_date);"
)

执行迁移后,所有带时间的字符串会被转换为纯日期格式,报错即可消失。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:57:04