You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django序列化器更新时创建新对象而非编辑现有对象的问题

解决Django ModelSerializer更新时id字段丢失导致update_or_create重复创建的问题

问题原因

PutAwayProductsPosition模型未显式定义主键字段,Django自动生成的id字段在ModelSerializer中默认是只读的。即使你传入了id值,序列化器在验证阶段会自动过滤掉该字段,导致validated_data中的子对象没有id,最终update_or_create因找不到匹配的主键而创建新条目。

解决方案

1. 修改子序列化器,显式开启id字段的写入权限

在PutAwayProductsPositionSerializer中显式声明id字段,并设置required=False(因为创建子对象时不需要传入id):

class PutAwayProductsPositionSerializer(serializers.ModelSerializer):
    # 显式声明id字段,允许写入,创建时可选
    id = serializers.IntegerField(required=False)

    class Meta:
        model = PutAwayProductsPosition
        fields = "__all__"

这样修改后,序列化器会接受传入的id值,并将其保留在验证后的validated_data中。

2. 优化update方法逻辑(可选,提升严谨性)

因为创建子对象时不需要传id,可以在update方法中增加判断,区分更新和创建场景:

def update(self, instance, validated_data):
    items_objects = validated_data.pop('products_position', [])
    prdcts = []
    for item in items_objects:
        # 取出id,不存在则返回None
        item_id = item.pop('id', None)
        if item_id:
            # 存在id则更新已有记录
            kp_instance, created = PutAwayProductsPosition.objects.update_or_create(
                pk=item_id, defaults=item
            )
        else:
            # 不存在id则创建新记录
            kp_instance = PutAwayProductsPosition.objects.create(**item)
        prdcts.append(kp_instance.pk)
    instance.products_position.set(prdcts)
    # 调用父类方法更新PutAway的其他字段
    return super().update(instance, validated_data)

验证效果

修改完成后,传入的子对象id会被保留在validated_data中,update_or_create能够通过pk=item_id找到对应的已有记录,执行更新操作而非创建新条目。

内容的提问来源于stack exchange,提问作者Rahul Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:28:27