3

这是我的看法:

class SectorListAPI(generics.ListAPIView):
    queryset = SectorModel.objects.all()
    serializer_class = SectorSerializer

这是我的序列化程序:

class OrganizationSerializer(serializers.ModelSerializer):
class Meta:
    model = GroupProfile
    fields = ('title','slug',)



class DepartmentSerializer(serializers.ModelSerializer):
    organizations = OrganizationSerializer(many=True, read_only=True)
    class Meta:
        model = DepartmentModel
        fields = ('title', 'organizations',)


class SectorSerializer(serializers.ModelSerializer):
    # title = serializers.CharField()
    departments = DepartmentSerializer(many=True, read_only=True)

    class Meta:
        model = SectorModel
        fields = ('title','departments',)

看,这里的“SectorSerializer”是父“ DepartmentSerializer ”是孩子,“ OrganizationSerializer ”是孙子序列化器。现在在我看来,我可以轻松地为“ SectorModel ”过滤我的查询集。但是我如何过滤“ GroupProfile ”模型。

4

2 回答 2

4

您可能希望过滤查询集以确保仅返回与发出请求的当前经过身份验证的用户相关的结果。

您可以通过基于值的过滤来做到这一点request.user.

例如:

from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        This view should return a list of all the purchases
        for the currently authenticated user.
        """
        user = self.request.user
        return Purchase.objects.filter(purchaser=user)

编辑

您可以继承 ListSerializer并覆盖该to_representation方法。

默认情况下,该to_representation方法调用data.all()嵌套查询集。因此,您实际上需要data = data.filter(**your_filters)在调用该方法之前进行。然后,您需要将您的子类 ListSerializer 添加为嵌套序列化程序元上的 list_serializer_class。

1-子类ListSerializer,覆盖to_representation然后调用super

2-在嵌套的序列化器上添加子类ListSerializer作为元。list_serializer_class

与您相关的代码:

class FilteredListSerializer(serializers.ListSerializer):

def to_representation(self, data):
    data = data.filter(user=self.request.user, edition__hide=False)
    return super(FilteredListSerializer, self).to_representation(data)


class OrganizationSerializer(serializers.ModelSerializer):
class Meta:
    list_serializer_class = FilteredListSerializer
    model = GroupProfile
    fields = ('title','slug',)



class DepartmentSerializer(serializers.ModelSerializer):
    organizations = OrganizationSerializer(many=True, read_only=True)
    class Meta:
        model = DepartmentModel
        fields = ('title', 'organizations',)


class SectorSerializer(serializers.ModelSerializer):
    # title = serializers.CharField()
    departments = DepartmentSerializer(many=True, read_only=True)

    class Meta:
    model = SectorModel
    fields = ('title','departments',)
于 2018-10-10T06:44:51.240 回答
0

感谢 @ans2human 提供此答案背后的灵感。

这是一种对我很有用的新方法。我有几个需要在嵌套关系中过滤掉的Models 。is_active = BooleanField(...)

注意:此解决方案不会过滤掉非列表字段的结果。为此,你应该看看你的querysetView

工作的核心是通过在 custom和伴随to_representation()的 custom 上重载函数来完成的:ListSerializermany_initModelSerializer

class FilteredListSerializer(serializers.ListSerializer):
    filter_params:dict
    def __init__(self, *args, filter_params:dict={"is_active":True}, **kwargs):
        super().__init__(*args, **kwargs)
        self.filter_params = filter_params

    def set_filter(self, **kwargs):
        self.filter_params = kwargs

    def to_representation(self, data):
        data = data.filter(**self.filter_params)
        return super().to_representation(data)

class FilteredModelSerializer(serializers.ModelSerializer):

    LIST_SERIALIZER_KWARGS = serializers.LIST_SERIALIZER_KWARGS + ("filter_params",)
    LIST_ONLY_KWARGS = ('allow_empty', 'filter_params')

    @classmethod
    def many_init(cls, *args, **kwargs):
        list_kwargs = dict()
        for arg in cls.LIST_ONLY_KWARGS:
            value = kwargs.pop(arg, None)
            if value is not None:
                list_kwargs[arg] = value
        child_serializer = cls(*args, **kwargs, **({"read_only":True} if "read_only" not in kwargs else dict()))
        list_kwargs['child'] = child_serializer
        list_kwargs.update({
            key: value for key, value in kwargs.items()
            if key in cls.LIST_SERIALIZER_KWARGS
        })
        meta = getattr(cls, 'Meta', None)
        list_serializer_class = getattr(meta, 'list_serializer_class', FilteredListSerializer)
        return list_serializer_class(*args, **list_kwargs)

然后,您ModelSerializer对任何视图的自定义将改为扩展FilteredModelSerializer

class ChildSerializer(FilteredModelSerializer):
    is_active = BooleanField() # not strictly necessary, just for visibilty
    ... # the rest of your serializer

class ParentSerializer(serializers.ModelSerializer):
    children = ChildSerializer(many=True)
    ...# the rest of your parent serializer

现在,childrenParentSerializer 上的字段将过滤is_active = True.

如果您有想要应用的自定义查询,您可以通过提供标准格式dict的过滤器参数来实现:queryset

class ParentSerializer(serializers.ModelSerializer):
    children = ChildSerializer(many=True, filter_params={"my_field":my_value, "my_datetime__gte": timezone.now()})
    ...# the rest of your parent serializer

或者,也可以在实例化字段之后使用该set_filter(...)方法,就像这样。FilteredListSerializer这将为原始QuerySet.filter(...)样式生成更熟悉的格式:

class ParentSerializer(serializers.ModelSerializer):
    children = ChildSerializer(many=True)
    children.set_filter(my_field=my_value, my_datetime__gte=timezone.now())
    ...# the rest of your parent serializer
于 2021-09-16T18:00:17.727 回答