问题
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:
- 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? - 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? - 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