Django REST Framework无法创建多联系人及邮箱 迁移报错咨询
问题排查
- 外键字段配置错误:
Email模型的user_emails字段、PhoneNum模型的user_contacts字段仅设置了blank=True,未设置null=True。blank=True仅控制Django表单校验层面是否允许为空,数据库层面默认仍为非空约束,当数据库中已经存在Email/PhoneNum的历史数据时,新增/修改外键字段就会触发需要默认值的提示。 PhoneNum模型语法错误:__str__方法尝试返回self.phone_num,但实际字段名为contact_num,运行时会触发属性不存在报错。- 序列化器配置错误:
MultipleSerializer的Meta.model参数同时传入了两个模型Email, PhoneNum,DRF的ModelSerializer仅支持绑定单个模型,该配置无法正常运行。 - 序列化器字段不匹配:
MultipleSerializer中定义的contacts字段,和PhoneNum模型的外键反向关联名contact_numbers不一致,无法正常读取关联数据。
解决方案
1. 修复模型字段配置
根据业务需求选择对应修改方案:
- 方案A:如果允许邮箱/手机号不绑定联系人,修改外键字段补充
null=True,同时修正PhoneNum的__str__方法:
# models.py 修正后代码 class Contact(models.Model): full_name = models.CharField(max_length=30, unique=True) nick_name = models.CharField(max_length=30, unique=True) status = models.BooleanField(default=1) def __str__(self): return self.full_name class Meta: ordering = ['full_name'] class Email(models.Model): email = models.EmailField(max_length=30) user_emails = models.ForeignKey( Contact, on_delete=models.CASCADE, related_name='emails', blank=True, null=True) def __str__(self): return self.email class PhoneNum(models.Model): contact_num = models.CharField(max_length=30) user_contacts = models.ForeignKey( Contact, on_delete=models.CASCADE, related_name="contact_numbers", blank=True, null=True) def __str__(self): # 修正字段名引用错误 return self.contact_num
- 方案B:如果业务要求每个邮箱/手机号必须绑定一个联系人,不需要留空,可以直接删除项目中之前生成的未应用的迁移文件,同时清空测试数据库中
Email、PhoneNum表的历史数据,不需要额外修改外键配置。
2. 修复序列化器配置
要实现查询联系人时同时返回关联的所有邮箱和手机号,直接修改ContactSerializer即可,无需单独定义MultipleSerializer:
# serializers.py 修正后代码 from django.db.models import fields from rest_framework import serializers from .models import Contact, Email, PhoneNum class ContactSerializer(serializers.ModelSerializer): # 读取关联的邮箱和手机号列表 emails = serializers.StringRelatedField(many=True, read_only=True) contact_numbers = serializers.StringRelatedField(many=True, read_only=True) class Meta: model = Contact fields = ['id', 'full_name', 'nick_name', 'status', 'emails', 'contact_numbers']
如果需要支持创建联系人时同时提交关联的邮箱和手机号,补充重写create方法即可。
3. 重新执行迁移
修复完成后,删除app/migrations/目录下除了__init__.py之外的所有迁移文件,依次执行以下命令即可完成迁移:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Sujan Joshi
相关产品推荐
相关产品推荐

