Django REST框架平面,读写串行器 [英] Django REST framework flat, read-write serializer

查看:122
本文介绍了Django REST框架平面,读写串行器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



例如,如何提供 User UserProfile 关系,下面?

 #模型
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',]

T他以上 UserProfileSerializer 不允许写入电子邮件字段,但我希望它表达的意图足够好。那么,应该如何构造一个平面读写序列化程序来允许 UserProfileSerializer 上的可写电子邮件属性?在将ModelSerializer子类化时,是否可以这样做?



谢谢。

解决方案>

查看Django REST框架(DRF)源代码,我确定了一个DRF序列化器与附带的模型绑定在一起,用于取消排序。 字段 param使序列化目的更少。



考虑到这一点,并且查看序列化程序作为封装验证和保存行为(除了它们的(un)序列化行为之外),我使用了两个序列化器:每个User和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',]

source param on EmailField 充分处理序列化案例(例如,在服务GET请求时)。对于非串行化(例如,当排除PUT请求时),必须在视图中进行一些工作,结合两个序列化程序的验证和保存行为:

 code> class UserProfileRetrieveUpdate(generics.GenericAPIView):
def get(self,request,* args,** kwargs):
#只有使用UserProfileSerializer来序列化数据,因为
#email由EmailField上的source参数填充。
serializer = UserProfileSerializer(
instance = request.user.get_profile())
返回响应(serializer.data)

def put(self,request,* args ,** kwargs):
#为了验证和保存关联模型上的数据,需要使用UserProfileSerializer和UserProfileSerializer
#。
user_profile_serializer = UserProfileSerializer(
instance = request.user.get_profile(),
data = request.DATA)
user_serializer = UserSerializer(
instance = request.user,
data = request.DATA)
如果user_profile_serializer.is_valid()和user_serializer.is_valid():
user_profile_serializer.save()
user_serializer.save()
返回响应(
user_profile_serializer.data,status = status.HTTP_200_OK)
#组合两个序列化器的错误。
errors = dict()
errors.update(user_profile_serializer.errors)
errors.update(user_serializer.errors)
返回响应(errors,status = status.HTTP_400_BAD_REQUEST)


In Django REST framework, what is involved in creating a flat, read-write serializer representation? The docs refer to a 'flat representation' (end of the section http://django-rest-framework.org/api-guide/serializers.html#dealing-with-nested-objects) but don't offer examples or anything beyond a suggestion to use a RelatedField subclass.

For instance, how to provide a flat representation of the User and UserProfile relationship, below?

# 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',]

The above UserProfileSerializer doesn't allow writing to the email field, but I hope it expresses the intention sufficiently well. So, how should a 'flat' read-write serializer be constructed to allow a writable email attribute on the UserProfileSerializer? Is it at all possible to do this when subclassing ModelSerializer?

Thanks.

解决方案

Looking at the Django REST framework (DRF) source I settled on the view that a DRF serializer is strongly tied to an accompanying Model for unserializing purposes. Field's source param make this less so for serializing purposes.

With that in mind, and viewing serializers as encapsulating validation and save behaviour (in addition to their (un)serializing behaviour) I used two serializers: one for each of the User and UserProfile models:

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',]

The source param on the EmailField handles the serialization case adequately (e.g. when servicing GET requests). For unserializing (e.g. when serivicing PUT requests) it is necessary to do a little work in the view, combining the validation and save behaviour of the two serializers:

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)

这篇关于Django REST框架平面,读写串行器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆