如何将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
相关产品推荐
相关产品推荐

