Reputation: 1886
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.
Upvotes: 9
Views: 3999
Reputation: 2249
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, self).to_representation(iterable)
# use overridden FilteredManyRelatedField in `many_init`
class FilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
@classmethod
def many_init(cls, *args, **kwargs):
kwargs['child_relation'] = cls(queryset=kwargs.pop('queryset'))
return FilteredManyRelatedField(*args, **kwargs)
Upvotes: 4
Reputation: 1015
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)
Upvotes: 12