Friday, April 29, 2016

Django-REST Serializer: Queryset does not filter PrimaryKeyRelatedField results

1 comment

So I have a serializer that looks like this

class BuildingsSerializer(serializers.ModelSerializer):     masterlisting_set = serializers.PrimaryKeyRelatedField(many=True,                                      queryset=Masterlistings.objects.all()) 

and it works great

serializer = BuildingsSerializer(Buildings.objects.get(pk=1)) serializer.data  

produces

OrderedDict([     ("masterlistings_set", [         "0a06e3d7-87b7-4526-a877-c10f54fa5bc9",         "343643ac-681f-4597-b8f5-ff7e5be65eef",         "449a3ad2-c76c-4cb8-bb86-1be72fafcf64",     ]) ]) 

but if I change the queryset in the serializer to

class BuildingsSerializer(serializers.ModelSerializer):      masterlistings_set = serializers.PrimaryKeyRelatedField(many=True, queryset=[]) 

I still get the same exact result back.

 OrderedDict([     ("masterlistings_set", [         "0a06e3d7-87b7-4526-a877-c10f54fa5bc9",         "343643ac-681f-4597-b8f5-ff7e5be65eef",         "449a3ad2-c76c-4cb8-bb86-1be72fafcf64",     ]) ]) 

Is this supposed to be happening? Am I using querysets incorrectly? I used [] as an easy example to show that no matter what I put in nothing changes.

Please any insight would be invaluable

It should be noted that masterlistings has a primary key relationship that points to buildings. So a masterlisting belong to a building.

2 Answers

Answers 1

As pointed out by @zymud, queryset argument in PrimaryKeyRelatedField is used for validating field input for creating new entries. Another solution for filtering out masterlistings_set is to use serializers.SerializerMethodField() as follows:

class BuildingsSerializer(serializers.ModelSerializer):     masterlisting_set = serializers.SerializerMethodField()      def get_masterlisting_set(self, obj):         return MasterListing.objects.filter(building=obj).values_list('pk',flat=True) 

Answers 2

queryset in related field limits only acceptable values. So with queryset=[] you will not be able to add new values to masterlisting_set or create new Buildings.

UPDATE. How to use queryset for filtering

This is a little bi tricky - you need to rewrite ManyRelatedField and many_init method in your RelatedField.

# re-define ManyRelatedField `to_representation` method to filter values # based on queryset class FilteredManyRelatedField(serializers.ManyRelatedField):     def to_representation(self, iterable):         iterable = self.child_relation.queryset.filter(             pk__in=[value.pk for value in iterable])         return super(FilteredManyRelatedField).to_representation(iterable)   # use overridden FilteredManyRelatedField in `many_init` class FilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):     @classmethod     def many_init(cls, *args, **kwargs):         kwargs['child'] = cls()         return FilteredManyRelatedField(*args, **kwargs) 
If You Enjoyed This, Take 5 Seconds To Share It

1 comment:

  1. hi,for excellent videos on soapui
    refer
    http://soapui-tutorial.com/soapui-tutorial/introduction-to-webservices/

    ReplyDelete