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

Django Rest Framework UpdateAPIView提示campaign必填但已传值

问题原因及解决方法

核心原因

你在BigAdSerializer里给campaign字段用了嵌套序列化器ShortCampaignSerializer,而DRF(Django REST Framework)的嵌套序列化器默认不支持直接接收主键值来更新关联关系——它期望收到的是符合ShortCampaignSerializer结构的完整对象数据,而不是单纯的主键字符串"20"。

反观audience字段,它应该是用了DRF默认的外键序列化方式(比如PrimaryKeyRelatedField),这种字段可以直接接收主键值完成关联更新,所以没有报错。

具体解决思路

针对这个问题,有三种常用的处理方式:

1. 动态切换字段序列化类型

在序列化器中,分别处理序列化输出和反序列化输入的字段类型:

class BigAdSerializer(serializers.ModelSerializer):
    class Meta:
        model = BigAd
        fields = ['id', 'campaign', 'audience', ...]

    def to_representation(self, instance):
        # 序列化输出(返回给前端)时用嵌套序列化器
        self.fields['campaign'] = ShortCampaignSerializer()
        return super().to_representation(instance)

    def to_internal_value(self, data):
        # 反序列化输入(前端提交数据)时用主键字段
        self.fields['campaign'] = serializers.PrimaryKeyRelatedField(queryset=Campaign.objects.all())
        return super().to_internal_value(data)

2. 重写序列化器的update方法

手动提取主键值并关联到对应对象:

class BigAdSerializer(serializers.ModelSerializer):
    campaign = ShortCampaignSerializer()

    class Meta:
        model = BigAd
        fields = ['id', 'campaign', 'audience', ...]

    def update(self, instance, validated_data):
        # 单独处理campaign的主键值
        campaign_id = validated_data.pop('campaign', None)
        if campaign_id:
            instance.campaign = Campaign.objects.get(pk=campaign_id)
        # 更新其他常规字段
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance

3. 拆分序列化器(更清晰的架构)

分别定义用于详情展示和更新操作的序列化器,在视图中按需使用:

# 详情展示用(带嵌套序列化器)
class BigAdDetailSerializer(serializers.ModelSerializer):
    campaign = ShortCampaignSerializer()
    class Meta:
        model = BigAd
        fields = ['id', 'campaign', 'audience', ...]

# 更新操作用(默认主键字段)
class BigAdUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = BigAd
        fields = ['id', 'campaign', 'audience', ...]

# 视图中指定更新用的序列化器
class UpdateBigAd(UpdateAPIView):
    queryset = BigAd.objects.all()
    serializer_class = BigAdUpdateSerializer

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:52:10