DRF Serializer使用update_or_create报Unique Constraint Failed错误
问题根因
- DRF 序列化器执行操作时,新增请求会调用
create()方法,更新请求会调用update()方法,你仅重写了create()方法,PUT 更新请求走的默认update()逻辑,完全没有处理part字段的类型转换:你在序列化器中定义part为CharField接收字符串参数,但模型中part是OneToOneField关联Part表,默认update()方法会直接把字符串写入外键字段,要么触发外键约束错误,要么写入的part值已经存在关联的DocumentRef记录,触发唯一约束错误。 - 你之前的
update_or_create写法参数错误:没有显式指定查询条件,所有传入字段都会作为查询条件,只要修改了任意文件字段,就会触发新建逻辑,而part是唯一索引,新建必然报错。 get_object方法返回值类型不统一,查询不到记录时返回HttpResponse而非异常,后续逻辑传入序列化器会触发额外错误。
修复方案
1. 修正序列化器逻辑,统一处理字段转换、新增/更新逻辑
class PartSerializer(serializers.ModelSerializer): part = serializers.CharField() class Meta: model = DocumentRef fields = ('part', 'field1', 'field2', 'field3') # 统一处理入参字段转换,新增、更新请求都会先执行该逻辑 def to_internal_value(self, data): internal_data = super().to_internal_value(data) # 把传入的part号字符串转换为Part实例 try: part_inst = Part.objects.get(part_number=internal_data['part']) internal_data['part'] = part_inst except Part.DoesNotExist: raise serializers.ValidationError({"part": "指定的Part记录不存在"}) return internal_data def create(self, validated_data): # 显式指定查询条件为part,其余字段作为更新值,避免误新建 doc_ref, _ = DocumentRef.objects.update_or_create( part=validated_data['part'], defaults=validated_data ) return doc_ref def update(self, instance, validated_data): # 更新前校验part唯一性:如果改了part值,要确认新值没有被其他记录占用 new_part = validated_data['part'] if new_part != instance.part and DocumentRef.objects.filter(part=new_part).exists(): raise serializers.ValidationError({"part": "该Part已关联其他DocumentRef记录"}) # 逐个更新字段 instance.part = new_part instance.field1 = validated_data.get('field1', instance.field1) instance.field2 = validated_data.get('field2', instance.field2) instance.field3 = validated_data.get('field3', instance.field3) instance.save() return instance
2. 修正视图的查询逻辑
from rest_framework.exceptions import NotFound class APIDetailTest(APIView): def get_object(self, pk): try: return DocumentRef.objects.get(pk=pk) except DocumentRef.DoesNotExist: # 抛出DRF标准异常,框架会自动返回404响应 raise NotFound("对应DocumentRef记录不存在") # get、put方法保持原有逻辑即可
内容的提问来源于stack exchange,提问作者Josh_At_Sorenson
相关产品推荐
相关产品推荐

