Django REST框架PUT/PATCH请求更新失败反而新建对象问题排查
问题核心原因
你遇到的更新时新建Product对象的问题,本质是作为主键的sku字段被修改触发了Django ORM的新建逻辑:
Django ORM的save()方法默认逻辑为:如果传入的实例对象主键值发生变更,会将当前数据作为全新的对象插入数据库,而非更新原有主键对应的记录。
结合你的代码场景,触发条件为:
你发起PUT/PATCH更新请求时,请求体中携带了sku字段,且该字段值和请求URL中传入的主键pk值不一致。序列化器在校验时会接收请求传入的sku值,覆盖原有实例的sku属性,调用save()时就会生成新的对象。
排查步骤
- 先抓包查看你发起更新请求的请求体内容,确认是否携带了
sku字段,且值和请求URL路径中的pk值不匹配 - 确认序列化器是否开放了sku字段的可写权限,你的现有代码把sku放在了普通fields列表中,默认是可写的,允许用户通过接口修改主键
解决方法
绝大多数业务场景下商品SKU作为唯一标识不会允许随意修改,最优解决方案是将sku字段设为序列化器只读字段:
修改ProductSerializer代码如下:
class ProductSerializer(serializers.ModelSerializer): class Meta: model = Product fields = [ "sku", "product_name", "product_price", "product_brand", "times_searched_anonymous" ] # 新增以下配置,sku设为只读,不允许通过接口修改 read_only_fields = ["sku"]
如果你确实有修改SKU的特殊需求,需要单独写逻辑:先删除原有SKU对应的记录,再用新的SKU值创建新对象,不推荐直接依赖默认save逻辑实现SKU修改。
另外补充两个你代码中的小问题,避免后续出其他异常:
- put方法中
return Response(serializer.data)前存在缩进错误,需要和上层if判断对齐 - patch方法更新成功后返回状态码201不符合REST规范,201是资源创建成功的状态码,更新成功应该返回200
内容的提问来源于stack exchange,提问作者Valter Núñez
相关产品推荐
相关产品推荐

