Django报错修复:1452, ‘Cannot add or update a child row: a foreign key constraint fails

本文讲述了如何处理Django中Admin后台修改User时遭遇的IntegrityError,涉及外键约束问题。作者发现是由于历史迁移记录导致的django_admin_log表与扩展User表不匹配,通过修改外键指向并修复数据库结构,解决了这个问题。
摘要由CSDN通过智能技术生成

Django admin后台,修改User表数据时,遇到报错:

django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`auto_center`.`django_admin_log`, CONSTRAINT `django_admin_log_user_id_c564eba6_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`))')

网上查了下,基本上都是说修改setting文件的databases,添加以下代码取消外键检查:

'OPTIONS': {
    "init_command": "SET foreign_key_checks = 0;",
}

但是,取消外键检查,会导致外键约束检查失效,会有隐患,乃是治标不治本的方法。

看报错的信息,是django_admin_log表的user_id,指向了外键是auth_user。但我的Django User模型有个扩展表,是指向了扩展的User表,而非Django原生的auth_user表。

查看django_admin_log源码,是指向settings.AUTH_USER_MODEL的。而我在settings里,已经配置过指向扩展User表了:

AUTH_USER_MODEL = 'auth.ExpandUser'

配置是生效的。我切换到测试环境,是不会有上面报错了,相同代码,只是切换了数据库,就会有报错。说明不是代码问题。

仔细思考了下,应该是线上环境,比较久远了,当初执行migrate的时候,django_admin_log表的user_id,指向了原生的auth_user。后来更新了扩展User表,测试环境的数据库是重新建立过的,重新执行的migrate,所以关联的外键是扩展User表,不会报错。

所以问题的原因必然是在现有的线上数据库的记录上。查了一圈,找到原因。是django_admin_log表的user_id字段,关联了外键auth_user。而测试环境的是关联的扩展User表。

在这里的引用表,修改成ExpandUser表。再回到admin后台修改User表数据 ,不再报错。

反思一下:之前一直是用Django的ORM管理映射关系的,不知道MySQL原生的外键是怎么管理的。今天遇到的问题,排查下来,就是由于历史的migrate记录,导致扩展User表的时候,数据库还记录旧的外键关系。而admin操作修改的时候,会记录日志到django_admin_log,记录user_id的时候,使用ExpandUser表的user_id记录到数据库时,触发了MySQL检查外键,指向auth_user表,而auth_user没有对应的user_id,就报错了。

知道原因,再回过头来看修复方法,就很简单了:

  1. 修改django_admin_log,把user_id关联的外键,改成自己定义的扩展User表
  2. 如果不想改,可以在测试环境(或新建个空的数据库),重新执行迁移,然后把新的django_admin_log表,通过数据库复制的方式,覆盖掉现有的django_admin_log表
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值