Django执行loaddata导入fixture时报created字段NOT NULL约束错误
问题原因
- Django的
auto_now_add、auto_now字段的自动赋值逻辑仅在ORM的save()方法执行时触发,而loaddata命令是直接批量写入数据库,不会调用模型的save()方法,因此这两个时间字段没有自动生成值。 - 你的模型中
created、last_updated字段仅设置了ORM层面的自动赋值逻辑,未设置数据库层面的默认值,直接写入空值就触发了SQLite的非空约束报错。 - 额外问题:fixture中的
user外键字段用数组包裹UUID值的写法不符合Django fixture格式要求,后续也会触发报错。
解决方法
方法1:直接补全fixture字段值(无需改动代码,最推荐)
修改start.json,给每条数据补充created、last_updated的合法ISO格式时间值,同时修正user字段的写法,修改后示例如下:
[ { "model": "app.estadual", "pk": "59472bb0-7f6e-4026-a900-727b7cdd647f", "fields": { "estado": "AC", "sigla": "AC", "valor": 12, "user": "4a695e40-6b3a-49fa-8beb-eed853ce17b0", "created": "2024-01-01T00:00:00Z", "last_updated": "2024-01-01T00:00:00Z" } }, { "model": "app.estadual", "pk": "5b321ca7-e8be-4580-8d36-080c663d5397", "fields": { "estado": "AL", "sigla": "AL", "valor": 12, "user": "4a695e40-6b3a-49fa-8beb-eed853ce17b0", "created": "2024-01-01T00:00:00Z", "last_updated": "2024-01-01T00:00:00Z" } } ]
修改完成后重新执行python.exe .\manage.py loaddata start.json即可。
注意:导入前请确认fixture中填写的user UUID对应的用户数据已存在于数据库中,否则会触发外键约束报错。
方法2:给时间字段添加数据库层面默认值(适合长期使用fixture的场景)
如果使用Django 3.2及以上版本,可以修改模型字段,添加db_default参数指定数据库层面的默认值,改动后需要生成并执行迁移:
from django.utils import timezone class Estadual(models.Model): # 其余字段保持不变 created = models.DateTimeField(auto_now_add=True, editable=False, db_default=timezone.now) last_updated = models.DateTimeField(auto_now=True, editable=False, db_default=timezone.now) # 其余字段保持不变
迁移生效后,fixture中不需要填写这两个时间字段也可以正常导入,同样记得修正fixture中user字段的数组写法。
内容的提问来源于stack exchange,提问作者marcelo.delta
相关产品推荐
相关产品推荐

