I have defined AViewSet
and ASerializer
for my AModel
:
class AModel(Model):
name = CharField(16)
text = TextField()
related = ForeignField('ARelated')
class AViewSet(ModelViewSet):
queryset = AModel.objects.all()
serializer_class = ASerializer
class ASerializer(Serializer):
class Meta(object):
model = AModel
fields = '__all__'
I wrote a RESTful client that posts a lot of data to that view/endpoint in multiple requests, creating many AModel
records. I have noticed, however that a significant part of the server time is spent on generating the response , and upon googling for a bit I found several references to the nested relationship hazard which seems like a decent fix, but got me wondering:
I already know what I posted and I don't need the pk
s, so could I prevent that serialization response from happening entirely? Can I instead just serialize the number of rows inserted?
Taking a look at DRF's CreateModelMixin
class:
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
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)
I realized I could override the create
method and reimplement it without returning the serializer.data
as part of the response, so it'll look similar to this:
def create(self, request, *args, **kwargs):
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({}, status=status.HTTP_201_CREATED, headers=headers)
I have two questions regarding this approach:
select
ing all the related data (as well as execute any SerializerMethodField
s, etc? Let's take the basic ModelViewset
and ModelSerializer
combination here :) It will be like,
# serializers.py
class SampleSerializer(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = '__all__'
# views.py
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
Why DRF returning all the data back to client ?
Here, the SampleViewset
is using SampleSerializer
everytime and it will serialilze all fields defined in the serializer class. As per the current configuration
What is the possible solution?
The possible solution is for this is stop serialization process of certain fields by some means :)
How to do?
As far as I knew, this can be done in two ways.
1. Use a minimal SampleSerializer
class for POST
method
2. override the to_representation()
method of SampleSerializer
on POST
requests
Method-1 : Use different serializer
Define a new serializer class with fields which are you wish to send and retrive while POST
request
class SampleSerializerMinimal(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = ('id', 'name', 'age')
Now, we've to tell viewsets to use this serializer for POST methods, it can be done in get_serializer_class()
of viewset
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
Method-2 : Override the to_representation()
method
class SampleSerializer(serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = '__all__'
What is the best way ?
I felt Method-1 is more DRF way of doing things, but you can't add id
only to the fields
because, POST request may require more fields.
The Method-2
to is also good, but its not much clean if you want to return n
fields, and writing it in your to_representation()
method
UPDATE-1
Method-3: Combination of method-1
and method-2
# serializer.py
class (serializers.ModelSerializer):
class Meta:
model = SampleModel
fields = ('id', 'name', 'age')
# views.py
class SampleViewset(viewsets.ModelViewSet):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
UPDATE-2
Does this practice of preventing the full serialization of objects created with a POST makes sense wrt RESTful design patterns, approach, ideology, etc?
the .data
is calling to_representation()
method, which calls the related objects and all other fields in the serializer . ( Source code of data
property of serializer ) So, if you can avoid that .data
call, it would be nice!.
Since I've seen many API responses with single detail like {"status":true}
after a POST request, I don't think your approch overkill the DRF patterns and other stuff
Will this actually avoid selecting all the related data (as well as execute any SerializerMethodFields, etc?
Yes. As I said above, It won't call the serializations process unless calling the .data
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.