Django创建LeadFacilityAssign时触发assigned_facilities_id非空约束错误
错误原因及修复方案
核心错误原因
- 循环取值逻辑错误:在
create方法的循环中,错误地使用整个assigned_facilities列表调用get()方法,而非循环中的单个facility字典。列表没有get()方法,导致返回None,最终向LeadFacilityAssign传入空值,触发非空约束错误。 - 请求字段与序列化器字段不匹配:请求JSON使用键名
facilities,但序列化器中定义的字段是assigned_facilities,导致无法正确解析设施数据(若前端未修正,validated_data.pop("assigned_facilities")会得到None,后续逻辑必然出错)。
额外潜在问题
- Lead模型缺少
agent字段:视图中serializer.save(agent=self.request.user)传入了agent参数,但Lead模型未定义该字段,会导致Lead创建失败。 facility_id类型不匹配:请求中facility_id是字符串"1",而ForeignKey关联的是整数类型的ID,可能引发类型错误。
修复步骤
1. 修正序列化器的create方法
将循环内的取值对象改为当前循环的facility字典,并转换facility_id为整数:
def create(self, validated_data): # 若前端传的是facilities,这里要改为validated_data.pop("facilities") assigned_facilities = validated_data.pop("assigned_facilities") instance = Lead.objects.create(**validated_data) for facility in assigned_facilities: # 使用当前循环的facility字典,而非整个列表 facility_id = int(facility.get('facility_id')) datetime_val = facility.get("datetime") instance.leadfacility.create(assigned_facilities_id=facility_id, datetime=datetime_val) return instance
2. 统一请求字段与序列化器字段
二选一即可:
- 修改请求JSON的键名为
assigned_facilities:
{"assigned_facilities": [{"facility_id": "1","datetime": "2018-12-19 09:26:03.478039"},{"facility_id": "1","datetime": "2018-12-19 09:26:03.478039"}]}
- 或修改序列化器的字段名为
facilities:
class LeadUpdateSerializer(serializers.ModelSerializer): is_owner = serializers.SerializerMethodField() facilities = serializers.JSONField(required=False, allow_null=True, write_only=True) class Meta: model = Lead fields = ("id","first_name","last_name","is_owner","facilities",) read_only_fields = ("id", "is_owner") def create(self, validated_data): assigned_facilities = validated_data.pop("facilities") # 后续逻辑不变 instance = Lead.objects.create(**validated_data) for facility in assigned_facilities: facility_id = int(facility.get('facility_id')) datetime_val = facility.get("datetime") instance.leadfacility.create(assigned_facilities_id=facility_id, datetime=datetime_val) return instance
3. 给Lead模型添加agent字段
from django.contrib.auth.models import User class Lead(models.Model): first_name = models.CharField(max_length=40, null=True, blank=True) last_name = models.CharField(max_length=40, null=True, blank=True) agent = models.ForeignKey(User, on_delete=models.CASCADE, related_name='leads') # 添加该字段 def __str__(self): return f"{self.first_name} {self.last_name}"
4. 可选:添加Facility存在性校验
避免传入不存在的facility_id导致错误:
from django.core.exceptions import ObjectDoesNotExist # 在循环内添加校验 try: facility = Facility.objects.get(id=facility_id) instance.leadfacility.create(assigned_facilities=facility, datetime=datetime_val) except ObjectDoesNotExist: # 可选择抛出异常、跳过该条目或记录日志 continue
内容的提问来源于stack exchange,提问作者Matthias
相关产品推荐
相关产品推荐

