Django REST Framework使用djongo执行migrate加外键字段报错如何解决
问题解决与方案说明
报错修复方案
你遇到的报错是djongo 1.3.4版本的功能限制导致的:该版本不支持ALTER TABLE ADD COLUMN NOT NULL类的SQL语句转MongoDB操作,触发场景是你在已存在数据的表中新增非空外键字段,Django默认会生成带非空约束的字段修改SQL,djongo无法解析该语句。
修复步骤如下:
- 临时修改外键字段配置,允许空值:将AnnotationModel和ModelPool的hospital字段改为
hospital = models.ForeignKey(Hostipal, on_delete=models.CASCADE, null=True, blank=True),执行python manage.py makemigrations生成迁移文件后,再执行python manage.py migrate完成首次迁移 - 给现有AnnotationModel和ModelPool数据补全hospital关联值,确保所有数据的hospital字段无空值
- 去掉hospital字段的
null=True, blank=True配置,重新执行makemigrations和migrate即可完成字段非空约束的设置。如果是全新无历史数据的项目,可以直接删除app下migrations目录中除__init__.py外的所有文件,重新生成迁移文件后执行migrate即可直接成功。
需求的其他实现方式
你当前的模型设计完全符合业务需求,还有两种可选实现方案可根据场景选择:
方案1:手动定义多对多中间表增加关联校验
适合需要严格限制跨医院模型关联的场景,可避免出现A医院的AnnotationModel被关联到B医院的ModelPool的异常数据:
# 新增多对多中间表 class ModelPoolAnnotationRel(models.Model): model_pool = models.ForeignKey(ModelPool, on_delete=models.CASCADE) annotation_model = models.ForeignKey(AnnotationModel, on_delete=models.CASCADE) hospital = models.ForeignKey(Hostipal, on_delete=models.CASCADE) class Meta: constraints = [ models.UniqueConstraint(fields=['model_pool', 'annotation_model'], name='unique_pool_model_rel') ] # 修改ModelPool的多对多字段配置 class ModelPool(models.Model): name = models.CharField(max_length=255, default='') modelsList = models.ManyToManyField(AnnotationModel, through=ModelPoolAnnotationRel, related_name="modelpool") hospital = models.ForeignKey(Hostipal, on_delete=models.CASCADE) def __str__(self): return self.name
方案2:精简字段减少冗余
适合不需要严格校验同医院关联、追求表结构精简的场景:直接去掉ModelPool的hospital外键字段,查询模型池所属医院时可通过model_pool.modelsList.all().values('hospital').distinct()关联AnnotationModel获取,仅需注意后续业务逻辑中保证同一个ModelPool关联的所有AnnotationModel属于同一家医院即可。
内容的提问来源于stack exchange,提问作者Strange Docter
相关产品推荐
相关产品推荐

