Django Rest Framework设置partial=True不生效 无法局部更新问题求助
问题排查&修复方案
1. 先修正视图层的核心错误
你第一个严重问题是序列化器传入的待更新实例完全错误:request.user是你的Account模型对象,不是要更新的BusinessPartner对象,视图的逻辑几乎全错,修正后代码如下:
class UpdatePartnerProfileView(generics.UpdateAPIView): permission_classes = [IsAuthenticated] serializer_class = BusinessPartnerSerializer # 重写get_object方法,直接返回当前用户关联的业务伙伴实例,不需要手动传参 def get_object(self): return BusinessPartner.objects.get(account=self.request.user) # 可选择直接删除自定义update方法,父类UpdateAPIView已经自带partial支持,你原有写法错误太多 # 如果要保留自定义update的话,正确写法如下 def update(self, request, *args, **kwargs): instance = self.get_object() # 第一个参数传正确的BusinessPartner实例,开启partial局部更新 serializer = self.serializer_class(instance, data=request.data, partial=True) if serializer.is_valid(raise_exception=True): self.perform_update(serializer) return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
你原来的视图错误点:
- 待更新实例传成了
request.user,导致后续序列化器逻辑全部混乱 - 缩进错误:最后一个return的缩进级别错误,应该和if同级
- 属性名错误:错误调用
serializer.error,正确属性是serializer.errors - 没有正确调用DRF内置的实例获取逻辑,手动传参导致逻辑错误
2. 修正序列化器的校验&更新逻辑
你的需求是“提交和原有值一致的手机号/邮箱时不触发唯一校验”,这个校验逻辑是在is_valid阶段执行的,你在update方法里删除validated_data的操作完全赶不上校验阶段,所以根本没用。
正确的做法是给unique字段添加exclude_current_instance的校验规则,同时简化update方法的冗余逻辑:
class BusinessPartnerSerializer(serializers.ModelSerializer): class Meta: model = BusinessPartner fields = [ "id", "first_name", "last_name", "mobile_number", "email", "business_name", "type_of_business", "street_address", "city", "state_province", "postal_zip", "services_offered", "account", ] extra_kwargs = { "id": {"read_only": True}, "account": {"read_only": True} # account是关联字段,不允许前端修改,设为只读 } # 给唯一字段添加校验,排除当前实例本身,更新时提交原有值不会触发唯一冲突报错 validators = [ serializers.UniqueTogetherValidator( queryset=BusinessPartner.objects.all(), fields=('mobile_number', 'email'), message="手机号或邮箱已被使用" ) ] def update(self, instance, validated_data): # instance本身就是要更新的BusinessPartner对象,不需要额外查询! # 你之前的额外查询是因为视图传错了实例才加上的冗余逻辑 # 不需要手动删validated_data里的手机号/邮箱,unique校验已经排除了自身冲突,直接更新即可 for (key, value) in validated_data.items(): setattr(instance, key, value) instance.save() return instance
你原来的序列化器错误点:
- 唯一字段没有排除当前实例,导致提交原有值时触发唯一校验报错,你误以为是需要填写所有字段
- update方法里重复查询数据库,冗余且逻辑错误
- account字段没有设置为只读,存在前端篡改关联账号的安全风险
3. 最终验证
修复后你可以只传递需要修改的字段,比如只传{"first_name": "张三"},不需要传其他字段即可完成局部更新;如果传递了和原有值一致的手机号/邮箱,也不会触发唯一冲突报错。
内容的提问来源于stack exchange,提问作者Justine
相关产品推荐
相关产品推荐

