Django Rest Framework: использование DynamicFieldsModelSerializer для исключения полей сериализатора - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть сериализатор, который используется в нескольких конечных точках (generics.ListAPIView), но в одной из них мне нужно скрыть поле сериализатора.Я бы предпочел не писать новый сериализатор просто для покрытия этого случая.

Начиная с DRF 3.0 у нас есть динамические поля для сериализаторов (https://www.django -rest-framework.org / api-guide / serializers/ # динамически-модифицирующие поля ), но у меня возникли некоторые проблемы, чтобы полностью понять, как их использовать.

Я создал этот сериализатор:

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)

Я хотел бы знать, является ли это хорошим решением.Спасибо!

1 Ответ

0 голосов
/ 27 февраля 2019

Добавьте этот фрагмент кода в метод __init__ класса сериализатора, как предложено в Документах DRF :

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