如何使用不同的Serializer反序列化POST请求

时间:2018-02-26 06:09:57

标签: django django-rest-framework

我正在尝试使用与从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

3 个答案:

答案 0 :(得分:3)

问题出在您的序列化程序中。您只是传递模型类extension YourViewController: UIWebViewDelegate { func webViewDidFinishLoad(_ webView: UIWebView) { let count = webView.pageCount // OR // when horizontal paging is required let count_horizontal = webView.scrollView.contentSize.width / webView.scrollView.frame.size.width; // when vertical paging is required let count_vertical = webView.scrollView.contentSize.height / webView.scrollView.frame.size.height; } } 作为create function的输出而不是Message对象

Message(message)

答案 1 :(得分:0)

您可以通过覆盖视图集的git clean -xdf方法来获取不同的序列化程序,具体取决于方法类型

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']) 的{​​{1}}方法以获得不同的输出

to_representation

答案 2 :(得分:0)

要使用不同的序列化程序,具体取决于序列化程序是否会对请求中的数据进行反序列化或序列化响应,您可以使用drf-rw-serializers

它有通用类来帮助您构建像Django REST Framework那样的视图,但是,它们使用serializer_classread_serializer_class而不是仅使用一个write_serializer_class

您可以在documentation中阅读有关安装和使用的更多说明。