Django 2.2升级至3.0时模型外键关联兼容性报错如何解决?
Django 2.2升级3.0多表继承外键兼容性问题解决方案
错误原因
Django 3.0 对多表继承场景下的外键关联规则做了更严格的校验:禁止外键的to_field参数指向子模型从父类继承来的非本地字段。你当前使用的是多表继承方案,Bancos是Pessoa的子类,idPessoa是父类Pessoa的主键,不属于Bancos的本地字段,因此触发了校验错误。
解决方案
方案一:无需修改数据库结构,仅调整模型代码(最推荐,适配你保留旧系统库结构的需求)
只需要在Bancos子模型中显式声明指向父类的关联字段,标记为parent_link,即可让Django识别idPessoa为Bancos的本地字段,原有逻辑完全兼容:
class Bancos(Pessoa): # 新增这一行显式指定父类关联 idPessoa = models.OneToOneField(Pessoa, on_delete=models.CASCADE, parent_link=True, primary_key=True, db_column='idPessoa') # 原有代码保持不变 @property def idBanco(self): return self.idPessoa @idBanco.setter def idBancoSetter(self,valor): self.idPessoa = valor codigo_febraban=models.CharField(max_length=5,null=True,blank=True) def __str__(self): return self.name
修改后运行python manage.py makemigrations生成迁移文件时,确认迁移文件没有修改现有表结构的ALTER语句即可执行迁移,不会影响现有数据。
方案二:调整外键关联逻辑,无需修改Bancos模型
如果不想改动Bancos的代码,也可以直接调整ContasBancariasPessoas中idBanco外键的关联规则,直接关联父类Pessoa的主键,同时限制查询范围为Bancos实例即可:
class ContasBancariasPessoas(models.Model): # 其他原有字段保持不变 # 注意修正原代码中Pessoas的笔误为Pessoa idPessoa = models.ForeignKey(Pessoa,limit_choices_to={'visivel':True},on_delete=models.CASCADE,to_field='idPessoa',verbose_name='titular') idBanco = models.ForeignKey( Pessoa, limit_choices_to={'bancos__isnull': False}, # 仅筛选属于Bancos的实例 on_delete=models.CASCADE, to_field='idPessoa', verbose_name="banco", related_name='bancos_contas', # 调整related_name避免冲突 null=True )
补充提示:原代码中
ContasBancariasPessoas的idPessoa外键关联的类名写为Pessoas(多了末尾的s),属于笔误,需要修正为Pessoa,否则会触发模型不存在的错误。
方案三:微调数据库结构(不推荐)
如果有重构需求可以给Bancos表新增本地主键字段idBanco,将外键关联指向该字段,需要做数据迁移,不符合保留旧库结构的需求,优先级最低。
内容的提问来源于stack exchange,提问作者Artur Fernandes de Souza Filho
相关产品推荐
相关产品推荐

