For example, I have a Person
model and its serializer
class Person(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
sex = models.IntegerField()
phone = models.CharField(max_length=255)
class SimplePersonSerializer(serializer.ModelSerializer):
class Meta:
model = Person
fields = ('first_name', 'last_name')
Then in my view function, I can:
@api_view(['GET'])
def people(request):
people = Person.objects.all()
data = SimplePersonSerializer(people, many=True).data
return Response(data)
However, when I profiler it using django-debug-toolbar
, it shows that the serializer ask SQL Server
to select all field of Person
model, despite I only need first_name
and last_name
.
I know I can change people = Person.objects.all()
to people = Person.objects.all().only('first_name', 'last_name')
to make it. But I wonder if I can do this inside the serializer.
You can create dynamic field serializer
for this and get the field data dynamically.
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
class SimplePersonSerializer(DynamicFieldsModelSerializer):
class Meta:
model = Person
fields = '__all__'
And then you can use it in your views like this.
@api_view(['GET'])
def people(request):
fields = ('first_name', 'last_name')
people = Person.objects.all().only(fields)
data = SimplePersonSerializer(people, many=True, fields = fields).data
return Response(data)
This helps to improve performance
because it will fetch only the required data. (when using Person.objects.all().only('first_name', 'last_name')
to fetch specific data)
You get all the fields queried because that's the query that runs by default when you do .all
etcetera. You only limit the fields (SELECT field1, field2, ...) when you do .only
, .values
, or .values_list
.
You can you can define the fields inside the serializer or you can go further and do dynamic things like: https://github.com/wimglenn/djangorestframework-queryfields
Inside the serializer:
class Meta:
fields = (*,...)
But, this is specific to the serializer. As the name implies this is just serializing the returned data into objects.
You can do queries in the serializer, but this typically for custom fields.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With