【问题标题】:Django Rest Framework: using DynamicFieldsModelSerializer for excluding serializer fieldsDjango Rest Framework:使用 DynamicFieldsModelSerializer 排除序列化器字段
【发布时间】:2019-07-20 11:47:32
【问题描述】:

我有一个用于几个端点(generics.ListAPIView)的序列化程序,但在其中一个端点中我需要隐藏一个序列化程序字段。我宁愿不写一个新的序列化程序来覆盖这种情况。

从 DRF 3.0 开始,我们有用于序列化程序的动态字段 (https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields),但我在完全理解如何使用它们时遇到了一些麻烦。

我创建了这个序列化程序:

class TestSerializer(DynamicFieldsModelSerializer):
    user_req = UserSerializer(read_only=True)
    user_tar = UserSerializer(read_only=True)

    class Meta:
        model = TestAssoc
        fields = ("user_req", "user_tar")

这是我的终点:

class TestEndpointListAPIView(generics.ListAPIView):
    serializer_class = TestSerializer
    permission_classes = [IsAuthenticated]
    lookup_field = 'test_username'

    def get_queryset(self):
        return ...

现在我需要从输出中隐藏“user_tar”字段,根据文档,我应该使用以下内容实例化序列化程序:

TestSerializer(fields=('user_req'))

但是我应该如何在我的 TestEndpointListAPIView 中执行此操作?我应该覆盖 get_serializer 吗?

感谢您的帮助

编辑:

通过覆盖 get_serialized 函数,我找到了以下解决方案:

def get_serializer(self, *args, **kwargs):
    serializer_class = self.get_serializer_class()
    kwargs['context'] = self.get_serializer_context()
    kwargs['fields'] = ['user_req']
    return serializer_class(*args, **kwargs)

我想知道这是否是一个好的解决方案。谢谢!

【问题讨论】:

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


    【解决方案1】:

    按照DRF docs中的建议,将这段代码添加到序列化程序类的__init__方法中:

    class TestSerializer(serializers.ModelSerializer):
        user_req = UserSerializer(read_only=True)
        user_tar = UserSerializer(read_only=True)
    
        class Meta:
            model = TestAssoc
            fields = ("user_req", "user_tar")
    
    
        def __init__(self, *args, **kwargs):
            # Don't pass the 'fields' arg up to the superclass
            fields = kwargs.pop('fields', None)
    
            # Instantiate the superclass normally
            super(TestSerializer, self).__init__(*args, **kwargs)
    
            if fields is not None:
                # Drop any fields that are not specified in the `fields` argument.
                allowed = set(fields)
                existing = set(self.fields)
                for field_name in existing - allowed:
                    self.fields.pop(field_name)
    

    因此,当您从 views.py 调用序列化程序时,请执行以下操作:

    TestSerializer(queryset, fields=('user_req'))
    

    或者你可以做的是定义一个类

    class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    
        def __init__(self, *args, **kwargs):
            # Don't pass the 'fields' arg up to the superclass
            fields = kwargs.pop('fields', None)
    
            super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
    
            if fields is not None:
                allowed = set(fields)
                existing = set(self.fields)
                for field_name in existing - allowed:
                    self.fields.pop(field_name)
    

    现在导入这个类,如果你已经在其他文件中定义了它,然后使用继承它

    class TestSerializer(DynamicFieldsModelSerializer):
    

    这边:

    class TestSerializer(DynamicFieldsModelSerializer):
        user_req = UserSerializer(read_only=True)
        user_tar = UserSerializer(read_only=True)
    
        class Meta:
            model = TestAssoc
            fields = ("user_req", "user_tar")
    

    现在你可以做

    TestSerializer(queryset, fields=('user_req'))
    

    更新
    在意见。以ListAPIView为例

    class DemoView(ListAPIView):
        queryset = TestAssoc.objects.all()
    
        def get(self, request):
            try:
                queryset = self.get_queryset()
    
                data = TestSerializer(queryset, fields=('user_req')).data
    
                return Response( {"data" : data } ,status=status.HTTP_200_OK)
            except Exception as error:
                return Response( { "error" : str(error) } , status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    

    【讨论】:

    • 这是我最初的想法,但后来我不明白TestSerializer(queryset, fields=('user_req'))应该放在我的ListAPIView中的哪个位置。
    • 我更新了您现在可以查看的答案。我想它解决了你所有的疑问。如果解决了,请接受答案,以便其他人也能发现它有帮助
    • 抱歉,您的代码不起作用(我得到一个空的 json)。无论如何,它不是def get(self, request),而是def get(self, request, *args, **kwargs),不是{"data" : "data" },而是{"data" : data }。无论如何,问题是变量数据是空的。
    • 是的 "data" 这是一个已更新的错字。 *args, **kwargs 不是必需的,除非你需要它。 get 方法在没有它的情况下仍然可以工作。对于您在 data 变量中收到的空数据。那是因为TestAssoc.objects.all() 这里是空的。您没有任何TestAssoc 模型的数据。所以你得到的空json与我的代码无关。
    猜你喜欢
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 2018-06-07
    • 2015-07-01
    相关资源
    最近更新 更多