(Comments)
When using serializers with django rest framework
, retrieving all fields of the models might cause unnecessary traffic. This can be avoided with careful design.
Let us say we have a nested serializer called 'UserDataSerializer` with 5 fields each of which is a serializer in turn.
class UserDataSerializer(serializers.ModelSerializer): profile = ProfileSerializer(read_only=True) address = AddressSerializer(read_only=True) card = CardDetailsSerializer(read_only=True) portfolio = PortfolioSerializer(many=True, read_only=True) interests = InterestSerializer(many=True, read_only=True)
It is quite possible that each of the field itself holds a lot of data and could be unnecessary in some scenarios. Either way, if you do not want to serve all the fields and want to serve them based on the request here is the solution.
Let us say the requested fields are passed as part of the parameter tab
. For example, if the client only needs profile and address fields, the request URL would look like http://domain.com/path/to/data/?tab=profile&tab=address
. We can now dynamically include/exclude the fields based on the URL parameters. Add all the fields to the serializer Meta attribute fields.
class Meta: model = UserDataModel fields = ('profile', 'address', 'card', 'portfolio', 'interests')
With these values, the serializer initially includes all the fields (by class definition). But we can override the fields in the serializer's __init__
method. Here is how we build our custom __init__
method.
First we call the __init__
method defined in the super class.
def __init__(self, *args, **kwargs): # First call the __init__ method of super class super(WebsiteSerializer, self).__init__(*args, **kwargs)
Then we get the list of tabs requested from URL parameters.
if 'context' in kwargs: if 'request' in kwargs['context']: # Get the list of parameters named 'tab' as a python list tabs = kwargs['context']['request'].query_params.getlist('tab', [])
We can now set this list as the fields of the serializer with
self.fields = tabs
But it is possible that the list may contain undefined fields which cannot be served by the serializer and can result in exception. So we take care of this using sets. First remove duplicates in this list by constructing a set.
included = set(tabs)
Then we make a set of already existing fields and get a set of excluded fields.
existing = set(self.fields.keys()) excluded = existing - included
This set gives us the set of fields that needs to be excluded. Now we just pop the elements in the set from the fields of the serializer with
for other in excluded: self.fields.pop(other)
Our complete __init__
method will look like this.
def __init__(self, *args, **kwargs): super(WebsiteSerializer, self).__init__(*args, **kwargs) if 'context' in kwargs: if 'request' in kwargs['context']: tabs = kwargs['context']['request'].query_params.getlist('tab', []) if tabs: # tabs = tabs.split(',') included = set(tabs) existing = set(self.fields.keys()) for other in existing - included: self.fields.pop(other)
This serializer will include only those fields that are requested by the client. Hope this helps you as it did us.
We develop web applications to our customers using python/django/angular.
Contact us at hello@cowhite.com
Comments