Django Rest UpdateView报错:shop字段必填,如何设为更新可选/只读?
解决DRF中字段创建必填、更新可选的问题
针对你遇到的shop字段创建时必填、更新时无需传入的需求,提供三种可行方案:
方法1:动态调整字段必填属性(推荐)
重写序列化器的get_fields方法,通过判断是否存在实例(即是否为更新操作)来修改shop字段的必填规则:
class CampaignSerializer(serializers.ModelSerializer): class Meta: model = Campaign fields = '__all__' def get_fields(self): fields = super().get_fields() # 更新操作时(已有实例),设置shop字段非必填 if self.instance is not None: fields['shop'].required = False return fields
逻辑说明:创建操作时self.instance为None,保持shop字段的原有必填规则;更新操作时实例已存在,自动取消shop的必填限制。
方法2:拆分序列化器,视图动态切换
分别定义创建和更新专用的序列化器,在视图中根据请求方法切换使用:
# 创建用序列化器(shop默认必填) class CampaignCreateSerializer(serializers.ModelSerializer): class Meta: model = Campaign fields = '__all__' # 更新用序列化器(shop设为非必填) class CampaignUpdateSerializer(serializers.ModelSerializer): class Meta: model = Campaign fields = '__all__' extra_kwargs = { 'shop': {'required': False} } # 修改视图类 class CampaignUpdate(generics.RetrieveUpdateAPIView): queryset = Campaign.objects.all() permission_classes = [CampaignDetailPermission] lookup_field = 'cid' def get_serializer_class(self): if self.request.method in ('PUT', 'PATCH'): return CampaignUpdateSerializer return CampaignCreateSerializer
方法3:手动控制创建时的字段校验
先将shop设为非必填,再在创建逻辑中强制校验该字段:
class CampaignSerializer(serializers.ModelSerializer): shop = serializers.PrimaryKeyRelatedField( queryset=Shop.objects.all(), required=False ) class Meta: model = Campaign fields = '__all__' def create(self, validated_data): # 创建时必须传入shop,否则抛出校验错误 if 'shop' not in validated_data: raise serializers.ValidationError({'shop': 'This field is required.'}) return super().create(validated_data)
以上方案任选其一,即可实现创建时shop必填、更新时无需传入的需求,你的测试用例也能正常通过。
内容的提问来源于stack exchange,提问作者snake_case
相关产品推荐
相关产品推荐

