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

Django Rest Framework中使用PATCH添加嵌套字段实例的覆盖问题

解决DRF中PATCH请求更新多对多字段时覆盖原有实例的问题

问题原因

DRF的ModelSerializer默认对多对多字段的更新逻辑是替换关联集合:当你通过PATCH传入cards: [9]时,序列化器会将该Collector实例的所有关联Card替换为仅包含ID为9的实例,这就是原有实例被删除的原因。

解决方案

重写序列化器的update方法,自定义多对多字段的更新逻辑,实现追加新实例而非替换:

class SmallCollectorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Collector
        fields = ["id", "name", "email", "cards"]

    def update(self, instance, validated_data):
        # 从验证后的数据中提取cards字段(如果存在)
        cards_data = validated_data.pop('cards', None)
        
        # 先更新其他普通字段(调用父类的update方法)
        instance = super().update(instance, validated_data)
        
        # 如果传入了cards数据,执行追加操作
        if cards_data is not None:
            # 查询所有需要添加的Card实例
            new_cards = Card.objects.filter(id__in=cards_data)
            # 使用add方法批量添加,不会影响原有关联的Card实例
            instance.cards.add(*new_cards)
        
        return instance

说明

  • 上述代码先调用父类的update方法处理name、email等普通字段,再单独处理多对多的cards字段。
  • instance.cards.add(*new_cards)会把新的Card实例追加到现有关联集合中,不会删除原有实例。
  • 如果需要支持移除指定Card实例,可以额外添加逻辑(比如传入特定标识或单独字段),当前代码仅满足添加新实例的需求。

测试验证

假设原Collector实例的cards为[5, 6],发送PATCH请求:

{
    "cards": [9]
}

响应结果会变为:

{
    "id": 19,
    "name": "collector two",
    "email": "two@example.com",
    "cards": [5, 6, 9]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:07:17