如何使用自引用递归字段在DRF序列化程序中进行过滤

时间:2017-09-15 08:38:07

标签: python django python-3.x django-rest-framework

使用Python 3.x和Django Rest Framework。我有一个带有Recursive Field (自我)的序列化程序,它按预期工作。但是,我需要一种方法来初始过滤active = True返回的嵌套子项。

我已经尝试过不同的方法来过滤 active = True ,但是我无法在序列化程序中返回的嵌套子项上使用它。

这就是我所拥有的。

class MenuListSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
    children = RecursiveField(many=True, required=False)


class RecursiveField(serializers.Serializer):
    """
    Self-referential field for MPTT.
    """
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data

这是我尝试的但得到错误 ListSerializer'对象没有属性' queryset' 但是,我甚至不确定这会起作用。

class MenuListSerializer(serializers.ModelSerializer):

    def __init__(self, *args, request_user=None, **kwargs):
        # try and filter active in chrildrend before query set is passed
        super(MenuListSerializer, self).__init__(*args, **kwargs)
        # print(self.fields['children'].parent)
        self.fields['children'].queryset =     self.fields['children'].queryset.filter(active=True)

    url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
    children = RecursiveField(many=True, required=False)

1 个答案:

答案 0 :(得分:2)

如果我理解得很好,那么您正在尝试以分层方式序列化Menu个对象。 为此,我猜你会递归地序列化你的顶级菜单对象,不是吗? (否则你将获得顶层的所有Menu对象。)

为了能够仅过滤活跃的孩子,我建议您在模型上创建active_children属性:

class Menu(MPTTModel, TimeStampedModel):
    name = models.CharField(max_length=100)
    active = models.BooleanField(default=1)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    @property
    def active_children(self):
        return self.children.filter(active=True)

然后,您可以将其用作序列化程序中children字段的来源:

class MenuListSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='menu_detail')
    children = RecursiveField(many=True, required=False, source='active_children')

现在,在序列化时你应该只有活跃的孩子。

请注意,您还应该过滤查询集中的顶级对象,因为上面的过滤仅适用于Menu个对象中的子项。