Django-REST Serializer:Queryset不过滤PrimaryKeyRelatedField结果

时间:2016-04-20 21:43:15

标签: python django serialization django-rest-framework

所以我有一个看起来像这样的序列化器

ActiveRecord::Base.connection.raw_connection.exec_params(...)

并且效果很好

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

产生

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

但如果我将序列化程序中的查询集更改为

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

我仍然得到同样的结果。

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

这应该发生吗?我错误地使用了查询集吗? 我用[]作为一个简单的例子来表明,无论我什么都没有改变。

请有任何见解是非常宝贵的

应该注意,主列表具有指向建筑物的主键关系。所以一个主人名单属于一个建筑物。

2 个答案:

答案 0 :(得分:8)

正如@zymud所指出的,PrimaryKeyRelatedField中的queryset参数用于验证字段输入以创建新条目。 过滤掉masterlistings_set的另一个解决方案是使用serializers.SerializerMethodField(),如下所示:

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)

答案 1 :(得分:2)

相关字段中的

queryset仅限制可接受的值。因此,对于queryset=[],您将无法向masterlisting_set添加新值或创建新的Buildings

<强>更新。如何使用queryset进行过滤

这有点棘手 - 您需要在ManyRelatedField中重写many_initRelatedField方法。

# 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)