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

如何将partial参数传递给Django REST Framework嵌套序列化器?

如何将partial参数传递给嵌套序列化器?

我在使用Django REST Framework时,遇到了嵌套序列化器无法继承父序列化器partial参数的问题,示例代码如下:

serializers.py

class ASerializer(serializers.Serializer):
    name = serializers.CharField()

    def validate(self, data):
        print("A", self.partial)
        return data


class BSerializer(serializers.Serializer):
    a = ASerializer(read_only=False)

    def validate(self, data):
        print("B", self.partial)
        return data  

views.py

class TestView(APIView):
    def get(self, request, format=None):
        content = {}
        return Response(content)

    def post(self, request, format=None):
        bsr = BSerializer(data=request.data, partial=True) # 希望将partial参数传递给嵌套的ASerializer
        if bsr.is_valid(raise_exception=True):
            return Response(bsr.data)
        else:
            return Response(bsr.error)  

当向TestView传递{"a":{"name":"test"}}时,控制台输出:

A False
B True  

补充说明

我使用partial参数是为了区分创建验证和更新验证:

  • 当partial=False时,必须提供username、password和user_type字段(创建逻辑);
  • 当partial=True时,执行更新验证逻辑,限制部分字段的修改。

嵌套序列化器的validate函数如下:

def validate(self, data):
    username = data.get("username")
    password = data.get("password")
    user_type = intTryParse(data.get("user_type"))

    if self.partial:
        # 更新验证逻辑
        if len(data.keys()) == 0:
            msg = _("Empty attribute set")
            raise serializers.ValidationError(msg, code="authorization")

        elif password:
            msg = _("Password changing not allowed from this api")
            raise serializers.ValidationError(msg, code="authorization")

        elif username or user_type:
            msg = _("Cannot edit username and user_type")
            raise serializers.ValidationError(msg, code="authorization")
    else:
        # 创建验证逻辑
        if username and password and user_type:
            if CustomUser.objects.filter(username=username,).exists():
                msg = _("Username is not available")
                raise serializers.ValidationError(msg, code="authorization")
        else:
            msg = _('Must include "username", "password" and "user_type".')
            raise serializers.ValidationError(msg, code="authorization")
    return data

需要解决的问题:如何让父序列化器BSerializer的partial参数传递给嵌套的ASerializer?


解决方案

方法1:重写父序列化器的__init__方法,手动传递partial参数

在BSerializer的初始化方法中,将自身的partial属性赋值给嵌套的ASerializer字段:

class BSerializer(serializers.Serializer):
    a = ASerializer(read_only=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 将父序列化器的partial参数传递给嵌套的ASerializer
        self.fields['a'].partial = self.partial

    def validate(self, data):
        print("B", self.partial)
        return data  

此时再请求接口,控制台输出会变为:

A True
B True  

方法2:自定义嵌套字段类(复用性更高)

如果多个嵌套序列化器都需要传递partial参数,可以自定义字段类,自动继承父序列化器的partial属性:

class PartialNestedSerializerField(serializers.Field):
    def __init__(self, serializer_class, **kwargs):
        self.serializer_class = serializer_class
        super().__init__(**kwargs)

    def to_internal_value(self, data):
        # 验证阶段传递partial参数
        serializer = self.serializer_class(data=data, partial=self.parent.partial)
        serializer.is_valid(raise_exception=True)
        return serializer.data

    def to_representation(self, value):
        # 序列化阶段传递partial参数
        return self.serializer_class(value, partial=self.parent.partial).data

# 在父序列化器中使用自定义字段
class BSerializer(serializers.Serializer):
    a = PartialNestedSerializerField(ASerializer, read_only=False)

    def validate(self, data):
        print("B", self.partial)
        return data  

方法3:验证时手动初始化嵌套序列化器

如果只需要在验证阶段传递partial,可以在父序列化器的字段验证方法中手动初始化嵌套序列化器并传入参数:

class BSerializer(serializers.Serializer):
    a = ASerializer(read_only=False)

    def validate_a(self, value):
        # 手动初始化ASerializer并传入partial参数
        serializer = ASerializer(data=value, partial=self.partial)
        serializer.is_valid(raise_exception=True)
        return serializer.data

    def validate(self, data):
        print("B", self.partial)
        return data  

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 07:15:38