Django rest framework - filtering for serializer field

DjangoDjango Rest-Framework

Django Problem Overview


I have question about Django REST-full framework.

When products have rendered into remote client, each of product takes a filed with filtered data.

For example, model may be like this.

 class Product(models.Model):
      name = models.CharField()
 
 class Like(models.Model):
      product = models.ForeignKey(Product, related_name="likes")

On the client, each likes of product counted with true value, not false.

So I tried with below code in the serializer.

class ProductSerializer(serializers.ModelSerializer):
    
    likes = serializers.PrimaryKeyRelatedField(many=True, queryset=Like.objects.filter(whether_like=True))

	class Meta:
		model = Product
    	fields = ('id', 'name', 'likes')

But, that is not working as I wanted.

What should I do?

The following is extra view code.

@api_view(['GET'])
def product_list(request, user_id, format=None):

	if request.method == 'GET':
		products = Product.objects.all()
		serializer = ProductSerializer(products, many=True)
  
		return Response(serializer.data)
 

Django Solutions


Solution 1 - Django

How about something like this:

class ProductSerializer(serializers.ModelSerializer):
    likes = serializers.SerializerMethodField()

    def get_likes(self, product):
        qs = Like.objects.filter(whether_like=True, product=product)
        serializer = LikeSerializer(instance=qs, many=True)
        return serializer.data

    class Meta:
        model = Product
        fields = ('id', 'name', 'likes')

**LikeSerializer omitted for brevity. Hope this helps.

Solution 2 - Django

Instead of SerializerMethodField, which causes one additional database query per object, you can now (starting with Django 1.7) use Prefetch objects in the queryset of your DRF ViewSet:

from rest_framework import viewsets
from django.db.models import Prefetch

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.prefetch_related(Prefetch(
        'likes',
        queryset=Like.objects.filter(like=True)))

The prefetch needs just one query, ensuring vastly superior performance compared to SerializerMethodField.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHaegyun JungView Question on Stackoverflow
Solution 1 - DjangomishbahView Answer on Stackoverflow
Solution 2 - DjangoEndre BothView Answer on Stackoverflow