Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a custom queryset to serializer in Django Rest Framework

I am using Django rest framework 2.3 I have a class like this

class Quiz():
    fields..

# A custom manager for result objects
class SavedOnceManager(models.Manager):                                                                                                                                                                                                
    def filter(self, *args, **kwargs):
        if not 'saved_once' in kwargs:
            kwargs['saved_once'] = True
        return super(SavedOnceManager, self).filter(*args, **kwargs)

class Result():
    saved_once = models.NullBooleanField(default=False, db_index=True,
                                         null=True)
    quiz = models.ForeignKey(Quiz, related_name='result_set')

    objects = SavedOnceManager()

As you see I have a custom manager on results so Result.objects.filter() will only return results that have save_once set to True

Now my Serializers look like this:

class ResultSerializer(serializers.ModelSerializer):                                                                                                                                                                                                    
      fields...

class QuizSerializer(serializers.ModelSerializer):                                                                                                                                                                                                      
    results = ResultSerializer(many=True, required=False, source='result_set')

Now if I serializer my quiz it would return only results that have saved_once set to True. But for a particular use case I want the serializer to return all objects. I have read that I can do that by passing a queryset parameter http://www.django-rest-framework.org/api-guide/relations/ in (further notes section). However when I try this

results = ResultSerializer(many=True, required=False, source='result_set',
                           queryset=
                               Result.objects.filter(
                               saved_once__in=[True, False]))

I get TypeError: __init__() got an unexpected keyword argument 'queryset' And looking at the source code of DRF(in my version atleast) it does not accept a queryset argument.

Looking for some guidance on this to see if this is possible... thanks!

like image 733
akotian Avatar asked Jul 09 '15 02:07

akotian


People also ask

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.

How do I pass extra data to a serializer?

To pass extra arguments to serializer Class in Python Django Rest Framework, we set the context argument to a dict with the values we want to pass to the serializer. to create a MyModelSerializer by calling MyModelSerializer with the context argument set to a dict. to get the context values with self.

How do you serialize a Queryset in DRF?

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. So in your case try this: ... venues = profile.


Video Answer


1 Answers

In my opinion, modifying filter like this is not a very good practice. It is very difficult to write a solution for you when I cannot use filter on the Result model without this extra filtering happening. I would suggest not modifying filter in this manner and instead creating a custom manager method which allows you to apply your filter in an obvious way where it is needed, eg/

class SavedOnceManager(models.Manager):                                                                                                                                                                                                
    def saved_once(self):
        return self.get_queryset().filter('saved_once'=True)

Therefore, you can query either the saved_once rows or the unfiltered rows as you would expect:

Results.objects.all()
Results.objects.saved_once().all()

Here is one way which you can use an additional queryset inside a serializer. However, it looks to me that this most likely will not work for you if the default manager is somehow filtering out the saved_once objects. Hence, your problem lies elsewhere.

class QuizSerializer(serializers.ModelSerializer):  
    results = serializers.SerializerMethodField()

    def get_results(self, obj):
        results = Result.objects.filter(id__in=obj.result_set)
        return ResultSerializer(results, many=True).data
like image 142
Mark Galloway Avatar answered Sep 18 '22 05:09

Mark Galloway