Django REST Framework中ViewSet更新含唯一字段模型报错
解决方案
问题根源
你当前的update方法中,初始化序列化器时没有传入要更新的instance对象,导致DRF将此次请求判定为「创建新Machine实例」而非「更新现有实例」。此时即使你把request.data['machine_number']设为原对象的值,DRF依然会触发唯一约束校验(因为原实例的machine_number已经存在于数据库中),从而抛出错误。
修正代码
修改update方法中序列化器的初始化逻辑,传入目标machine实例:
class MachineViewSet(viewsets.ViewSet): serializer_class = MachineSerializer queryset = Machine.objects.all() def update(self, request, pk): try: machine = Machine.objects.get(pk=pk) # 可选:如果不允许修改machine_number,可注释掉下面这行,后续在序列化器设置read_only # request.data['machine_number'] = machine.machine_number except Machine.DoesNotExist: response = build_custom_response(False, 'Machine not found', '') return Response(response, status=status.HTTP_404_NOT_FOUND) # 关键:传入instance参数,告知序列化器执行更新逻辑 serializer = self.serializer_class(instance=machine, data=request.data, partial=True) if serializer.is_valid(): serializer.save() serialized_data = serializer.data success = True message = "Machine updated successfully" status_code = status.HTTP_200_OK else: success = False status_code = status.HTTP_400_BAD_REQUEST err_msg = '\n' error_list = [(serializer.errors[error][0]).capitalize() for error in serializer.errors] message = err_msg.join(error_list) data = serialized_data if 'serialized_data' in locals() else '' response = build_custom_response(success, message, data) return Response(response, status=status_code)
额外优化(可选)
如果业务上不允许修改machine_number,可以直接在序列化器中将其设为只读字段,避免后续误操作:
class MachineSerializer(serializers.ModelSerializer): machine_number = serializers.IntegerField(read_only=True) class Meta: model = Machine fields = ('id', 'machine_number', 'count', 'variety', 'lycra_draft', 'feedback', 'csp')
这样即使请求中传入machine_number,序列化器也会忽略该字段,彻底避免唯一约束冲突问题。
内容的提问来源于stack exchange,提问作者D.Karthikeyan
相关产品推荐
相关产品推荐

