Django REST框架平面,读写串行器 [英] Django REST framework flat, read-write serializer
问题描述
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屋!