Django创建外键约束报150错误及数据库层级级联删除设置咨询
问题1:外键约束创建失败(errno 150 "Foreign key constraint is incorrectly formed")
报错原因
MySQL要求外键字段和被引用的主键字段类型完全匹配。你自定义的TinyIntField继承自AutoField,AutoField默认对应int类型,Django生成外键字段时会默认按照父类AutoField的类型创建int类型的外键,和tblroles表实际tinyint类型的role_id不匹配,因此触发报错。
解决方法
自定义TinyIntField时新增rel_db_type方法,显式指定外键关联时的匹配字段类型,修改后的自定义字段代码如下:
class TinyIntField(AutoField): def db_type(self, connection): return "tinyint(3) AUTO_INCREMENT" # 新增该方法指定关联字段类型 def rel_db_type(self, connection): return "tinyint(3)"
修改完成后删除已生成的错误迁移文件,重新执行python manage.py makemigrations和python manage.py migrate即可。
问题2:on_delete CASCADE未在数据库层面生效
原因
Django默认会在ORM层面处理级联删除逻辑,若要在数据库层面生成级联删除约束,需要确保外键配置和数据库全局配置都符合要求。
解决方法
第一步:修改外键配置
给ForeignKey显式指定db_constraint=True参数,该参数默认值为True,若之前有手动关闭需要重新开启:
class tblusers(models.Model): user_id = BigAutoField(primary_key=True) # 新增db_constraint=True参数 role = ForeignKey(tblroles, on_delete = models.CASCADE, db_constraint=True)
第二步:检查数据库全局配置
打开settings.py查看数据库配置,确认没有关闭外键约束的配置,比如移除如下配置项:
# 要删除的关闭外键配置 OPTIONS = {"init_command": "SET foreign_key_checks = 0"}
第三步:重新生成迁移
删除旧的迁移文件,重新执行迁移命令,此时数据库层面就会生成带级联删除的外键约束。
内容的提问来源于stack exchange,提问作者Pankaj
相关产品推荐
相关产品推荐

