Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rest framework - filtering for serializer field

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) 
like image 308
Haegyun Jung Avatar asked Feb 03 '15 21:02

Haegyun Jung


People also ask

How do I pass Queryset to serializer?

To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.

How do you pass extra context data to Serializers in Django REST framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.

Do we need Serializers in Django REST framework?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.


2 Answers

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.

like image 134
mishbah Avatar answered Oct 14 '22 10:10

mishbah


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.

like image 42
Endre Both Avatar answered Oct 14 '22 08:10

Endre Both