Where to put extra logic in django web API, in the view, or in the serializer?

萝らか妹 提交于 2019-12-11 16:38:26

问题


I have a DRF view which extends CreateModelMixin and GenericViewSet. In the body of the post request, I want to accept an extra field, which does not belong to the related model. Then, I want to pop that extra field, use it for other purposes. I do not want to put that extra field back to the http response because it is a big and complex object. To explain it better here is a sample json input and the response that I want to return to the user:

Request:

# request
{
    "name": "Why Nations Fail",
    "extra_field": {
        "my_keys": ["I'm", "a", "very", "big", "array", "object.", "..."]
    }
}

Response:

# response
{
    "id": 120
    "name": "Why Nations Fail"
}

My problem is, I can't decide where to do this pop this extra_field; in the view or in the serializer (which extends ModelSerializer). Currently, I managed to do that by extending the create method handler of my view. But according the books and tutorials I've read:

We should keep our views thin and our serializers thick.

Keeping this in mind, I have tried to pop the field in the serializer but I couldn't manage to do that, I think because I'm using ModelSerializer which gives an error when validating a non-existing model field extra_field.

What I've done so far:

Currently, I pop this extra_field by extending create of my view as follows:

# models.py

class Book(models.Model):
   name = models.CharField(max_length=255)
# serializers.py

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
# views.py

class BookViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def create(self, request, *args, **kwargs):
         # notice that I'm popping the extra field instead of getting.
        extra_field = request.data.pop("extra_field")
        do_something_with_extra_field(extra_field)

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data,
            status=status.HTTP_201_CREATED,
            headers=headers
        )

This solution exactly satisfies my needs up to now.

I have 3 questions:

  1. Should pop extra_field in the view, or in the serializer? In my opinion, my serializer has nothing to do with this logic, but what happened to the "thin view, thick serializers" then?
  2. If I should do that in the view, is my current implementation is right? Is it a good approach to extend view's create handler method?
  3. If I should do that in the serializer, so how can I do it?

来源:https://stackoverflow.com/questions/57002973/where-to-put-extra-logic-in-django-web-api-in-the-view-or-in-the-serializer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!