Django REST框架平板,读写串行器

Pau*_*per 13 serialization django-rest-framework

在Django REST框架中,创建扁平的读写串行器表示涉及什么?文档指的是"平面表示"(http://django-rest-framework.org/api-guide/serializers.html#dealing-with-nested-objects部分的末尾),但不提供示例或任何内容超出建议使用RelatedField子类.

例如,如何提供以下关系UserUserProfile关系的平面表示?

# Model
class UserProfile(models.Model):
    user = models.OneToOneField(User)
    favourite_number = models.IntegerField()

# Serializer
class UserProfileSerializer(serializers.ModelSerializer):
    email = serialisers.EmailField(source='user.email')
    class Meta:
        model = UserProfile
        fields = ['id', 'favourite_number', 'email',]
Run Code Online (Sandbox Code Playgroud)

以上内容UserProfileSerializer不允许写入email字段,但我希望它足够好地表达意图.那么,如何构造一个"扁平"读写串行器来允许一个可写email属性UserProfileSerializer呢?在继承ModelSerializer时是否可以这样做?

谢谢.

Pau*_*per 6

查看Django REST框架(DRF)源代码,我认为DRF序列化程序与附带的模型紧密相关,以便进行反序列化.Fieldsource帕拉姆使这个没有那么序列化的目的.

考虑到这一点,并查看序列化程序作为封装验证和保存行为(除了它们的(非)序列化行为)我使用了两个序列化程序:每个用户和UserProfile模型一个:

class UserSerializer(serializer.ModelSerializer):
    class Meta:
        model = User
        fields = ['email',]

class UserProfileSerializer(serializer.ModelSerializer):
    email = serializers.EmailField(source='user.email')
    class Meta:
        model = UserProfile
        fields = ['id', 'favourite_number', 'email',]
Run Code Online (Sandbox Code Playgroud)

处理序列化案例的source参数EmailField足够(例如,在服务GET请求时).对于反序列化(例如,当处理PUT请求时),有必要在视图中做一些工作,结合两个序列化器的验证和保存行为:

class UserProfileRetrieveUpdate(generics.GenericAPIView):
    def get(self, request, *args, **kwargs):
        # Only UserProfileSerializer is required to serialize data since
        # email is populated by the 'source' param on EmailField.
        serializer = UserProfileSerializer(
                instance=request.user.get_profile())
        return Response(serializer.data)

    def put(self, request, *args, **kwargs):
        # Both UserProfileSerializer and UserProfileSerializer are required
        # in order to validate and save data on their associated models.
        user_profile_serializer = UserProfileSerializer(
                instance=request.user.get_profile(),
                data=request.DATA)
        user_serializer = UserSerializer(
                instance=request.user,
                data=request.DATA)
        if user_profile_serializer.is_valid() and user_serializer.is_valid():
            user_profile_serializer.save()
            user_serializer.save()
            return Response(
                    user_profile_serializer.data, status=status.HTTP_200_OK)
        # Combine errors from both serializers.
        errors = dict()
        errors.update(user_profile_serializer.errors)
        errors.update(user_serializer.errors)
        return Response(errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)