Singe CRUD / request->response Operation two serializers #9630
-
G'Day, Cant seem to find an answer anywhere, so hoping for an idea/solution.
Within my app, depending upon the situation I use different serializers. which serializer is used is dyno-magically determined by the viewsets logic. i.e. I have a view serializer for ALL get requests with the creation of the object being dynamic, serializer wise. I have discovered recently that when creating an object, the correct serializer is used, however the serializer that is used for the JSON response is not the one I wish to use. Looking at the code for the create of an object, It uses the same serializer for the create and the JSON return. (or have i looked in the wrong area?)
Is this something I will be required to create a custom solution for? or is there a setting or process I have overlooked somewhere? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
I had this problem a few times and there are a few ways to solve the problem, depending on how much your request schema differs from your response schema. Generally speaking, I think it's a good idea to minimise the differences. I'll describe a few options I've adopted over time. ExampleLet's use a simple class BlogPost(models.Model):
author = models.ForeignKey("auth.User", on_delete=models.CASCADE)
title = models.CharField(max_length=255)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True) When a post of created, the author provides the title and body, and the other fields as derived from the request. When reading a post, however, we want to display its author and creation date. Solution 1: override the create methodWith the solution you mention, the implementation might look like this: # Serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("id", "first_name", "last_name", "username")
class CreateBlogPostSerializer(serializers.ModelSerializer):
"""Serializer for creating posts."""
class Meta:
model = BlogPost
fields = ("title", "body")
class BlogPostSerializer(CreateBlogPostSerializer):
"""Serializer for reading posts."""
author = UserSerializer()
class Meta:
model = BlogPost
fields = ("id", "author", "title", "body", "created_at")
# views
class BlogPostViewSet(CreateModelMixin, RetrieveModelMixin, GenericViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
def create(self, request, *args, **kwargs):
create_serializer = CreateBlogPostSerializer(
data=request.data,
context=self.get_serializer_context(),
)
create_serializer.is_valid(raise_exception=True)
post = create_serializer.save(author=self.request.user)
response_serializer = self.get_serializer(post)
headers = self.get_success_headers(response_serializer.data)
return Response(response_serializer.data, status=status.HTTP_201_CREATED, headers=headers) We override the
This is however duplicating a fair bit of boilerplate from DRF, so not ideal. Solution 2: override the
|
Beta Was this translation helpful? Give feedback.
I had this problem a few times and there are a few ways to solve the problem, depending on how much your request schema differs from your response schema. Generally speaking, I think it's a good idea to minimise the differences. I'll describe a few options I've adopted over time.
Example
Let's use a simple
BlogPost
model in an blogging application:When a post of created, the author provides the title and body, and the other fields as derived from the request. …