I am accessing the related field's data in my SerializerMethodField and there is a query for every object that is being rendered. My models look like (will keep short for brevity):
class Listing(models.Model):
variant = models.ForeignKey(to='Variant', related_name='variant_listings')
seller = models.ForeignKey(to='user.Seller', related_name='seller_listings')
locality = models.ForeignKey(to='user.Locality', blank=True, null=True)
price = models.IntegerField(blank=True, null=True)
Variant
, Seller
and Locality
are all related models.
My Viewset:
class ListingViewSet(viewsets.ModelViewSet):
"""Viewset class for Listing model"""
queryset = Listing.objects.all()
serializer_class = ListingSerializer
pagination_class = TbPagination
filter_backends = (filters.DjangoFilterBackend,)
filter_class = ListingFilter
def get_queryset(self):
listing_qs = Listing.objects.filter(status='active')
listing_qs = ListingSerializer.setup_eager_loading(listing_qs)
return listing_qs
And my serializer:
class ListingSerializer(serializers.ModelSerializer):
"""Serializer class for Listing model"""
@staticmethod
def setup_eager_loading(queryset):
queryset = queryset.prefetch_related('variant', 'seller', 'locality')
return queryset
@staticmethod
def get_car_link(obj):
variant_name_slug = obj.variant.name.replace(' ', '-').replace('+', '')
return '/buy-' + obj.seller.city.name.lower() + '/' + variant_name_slug
car_link = serializers.SerializerMethodField(read_only=True)
@staticmethod
def get_car_info(obj):
return {
'id': obj.id,
'variant_name': obj.variant.name,
'localities': obj.locality.name,
}
car_info = serializers.SerializerMethodField(read_only=True)
@staticmethod
def get_image_urls(obj):
caption_ids = [1, 2, 3, 5, 7, 8, 18]
attachments_qs = Attachment.objects.filter(listing_id=obj.id, caption_id__in=caption_ids)
image_urls = []
for attachment in attachments_qs:
url = str(obj.id) + '-' + str(attachment.file_number) + '-360.jpg'
image_urls.append(url)
return image_urls
image_urls = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Listing
fields = ('car_link', 'car_info', 'sort_by', 'image_urls')
For each listing returned by the listing viewset, there is a query for every related field accessed in the SerializerMethodField.
I found some related questions like this. But that didn't help. Also, I tried doing prefetch_related
on my get_queryset method of the viewset and also implemented eager loading with the help of this article. But nothing helped.
Is there any way to avoid these queries?
Edit
The get_car_info function written above, contains a few more fields (along with the ones already present) which are required separately in a nested JSON by the name of car_info in the final serialized data that is being rendered at the front end.