如何使用不同的Serializer反序列化POST请求
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用不同的Serializer反序列化POST请求相关的知识,希望对你有一定的参考价值。
我正在尝试使用与从Model派生的序列化程序不同的序列化程序在我的API端点中处理POST请求,并用于GET或PUT请求。 POSTed消息的格式与Model和GET / PUT的格式不同,必须在存储到数据库之前进行预处理。
作为我的问题的演示,我做了一个非常简单的模型和相应的API视图和序列化器:
class Message(models.Model):
message = models.CharField(max_length = 500)
class MessageSerializer(serializers.ModelSerializer):
class Meta:
model = Message
fields = ('message',)
class MessageViewSet(viewsets.ModelViewSet):
queryset = Message.objects.all().order_by('-pk')
serializer_class = MessageSerializer
这很好用。然后我尝试覆盖MessageViewSet.create()以不同方式处理POST请求。
class MessageSerializer_FromTo(serializers.Serializer):
sender = serializers.EmailField()
recipient = serializers.EmailField()
def create(self, validated_data):
message = "Message from <{sender}> to <{recipient}>".format(**validated_data)
return Message(message)
class MessageViewSet(viewsets.ModelViewSet):
queryset = Message.objects.all().order_by('-pk')
serializer_class = MessageSerializer
# Handle POST requests differently
def create(self, request, format=None):
message = MessageSerializer_FromTo(data = request.data)
if message.is_valid():
message.save()
return Response(message.data, status=status.HTTP_201_CREATED)
return Response(message.errors, status=status.HTTP_400_BAD_REQUEST)
基本上我想把这个JSON传递给POST / api / messages /
{"sender": "some@one.com", "recipient": "someone@else.org"}
GET / api / messages / 1 /应该返回
{"message": "Message from <some@one.com> to <someone@else.org>"}
但是,POST失败并显示以下消息:
Internal Server Error: /api/messages/
Traceback (most recent call last):
File ".../rest_framework/fields.py", line 441, in get_attribute
return get_attribute(instance, self.source_attrs)
File ".../rest_framework/fields.py", line 100, in get_attribute
instance = getattr(instance, attr)
AttributeError: 'Message' object has no attribute 'sender'
During handling of the above exception, another exception occurred:
[...]
AttributeError: Got AttributeError when attempting to get a value for field `sender` on serializer `MessageSerializer_FromTo`.
The serializer field might be named incorrectly and not match any attribute or key on the `Message` instance.
Original exception text was: 'Message' object has no attribute 'sender'.
[26/Feb/2018 05:09:08] "POST /api/messages/ HTTP/1.1" 500 19059
这只是为了显示问题,我在POST处理程序中做了更复杂的事情,但错误是这样的。
知道如何实现我的需求吗?即接受与模型字段完全不同的POST字段?
谢谢!
更新:完整的代码在这里:https://github.com/mludvig/drf-demo
问题出在您的序列化程序中。您只是将模型类Message(message)
作为create function的输出而不是Message对象传递
class MessageSerializer_FromTo(serializers.Serializer):
sender = serializers.EmailField(write_only=True)
recipient = serializers.EmailField(write_only=True)
message = serializers.CharField(read_only=True, max_length = 500)
def create(self, validated_data):
message = "Message from <{sender}> to <{recipient}>".format(**validated_data)
return Message.objects.create(message=message)
您可以通过覆盖视图集的get_serializer_class
方法,根据方法类型获取不同的序列化程序
class MessageViewSet(viewsets.ModelViewSet):
model = Message
def get_serializer_class(self):
serializers_class_map = {
'default': DefaultSerializer,
'create': CreateMessageSerializer,
}
return serializers_class_map.get(self.action, serializers_class_map['default'])
您也可以覆盖to_representation
的CreateMessageSerializer
方法以获得不同的输出
class CreateMessageSerializer(serializer.ModelSerializer):
class Meta:
model = Message
fields = (
'sender', 'recipient'
)
def to_representation(self, instance):
return {
'message': "Message from <{0.sender}> to <{0.recipient}>".format(instance)
}
要使用不同的序列化程序,具体取决于序列化程序是否将请求中的数据反序列化或序列化响应,您可以使用drf-rw-serializers。
它有一些通用类来帮助你构建像Django REST Framework那样的视图,但是,它们不使用一个serializer_class
,而是使用read_serializer_class
和write_serializer_class
。
您可以在documentation中阅读有关安装和使用的更多说明。
以上是关于如何使用不同的Serializer反序列化POST请求的主要内容,如果未能解决你的问题,请参考以下文章