@thinklab

Как использовать разные Serializer для GET и POST в Django Rest Framework?

Использую generics.RetrieveUpdateAPIView. Вот мой override get_serializer_class:
def get_serializer(self, ):
        print(self.request.method)
        if hasattr(self, 'request.method'):
            if self.request.method == 'GET':
                return StepResultSerializer
            if self.request.method == 'POST':
                return StepInputSerializer

Когда выполняю GET, print срабатывает но метод не возвращает сериализатор. В трейсе выводится ошибка:

TypeError: 'NoneType' object is not callable
args	
(<Game: Game object>,)
kwargs	
{'context': {'format': None,
             'request': <rest_framework.request.Request object at 0x7ff2a82925f8>,
             'view': <api.views.ListGamesByIdView object at 0x7ff2a8765c88>}}
self	
<api.views.ListGamesByIdView object at 0x7ff2a8765c88>
serializer_class	
None
  • Вопрос задан
  • 5330 просмотров
Решения вопроса 1
Собственно ошибка в некорректном использовании hasattr. Условие будет всегда False.

def get_serializer_class(self):
        print(self.request.method)
        if hasattr(self.request, 'method'):
            if self.request.method == 'GET':
                return StepResultSerializer
            if self.request.method == 'POST':
                return StepInputSerializer


Вообще в данном случае эта проверка избыточна, т.к. при использовании всех generic вьюх из DRF у реквеста данный аттрибут будет всегда.

def get_serializer_class(self):
        if self.request.method == 'GET':
            return StepResultSerializer
        else:
            return StepInputSerializer
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Guest007
@Guest007
Django, Python, Linux и всё такое...
Я использую такую конструкцию:
class MultiSerializerViewSetMixin(object):
    def get_serializer_class(self):
        """
        Смотрим на serializer class в self.serializer_action_classes, который представляет из себя 
        dict mapping action name (key) в serializer class (value), например::
        class MyViewSet(MultiSerializerViewSetMixin, ViewSet):
            serializer_class = MyDefaultSerializer
            serializer_action_classes = {
               'list': MyListSerializer,
               'my_action': MyActionSerializer,
            }

            @action
            def my_action:
                ...

        Если подходящих вхождений в action нет тогда просто fallback к обычному
        get_serializer_class lookup: self.serializer_class, DefaultSerializer.
        """
        try:
            return self.serializer_action_classes[self.action]
        except (KeyError, AttributeError):
            return super(MultiSerializerViewSetMixin, self).get_serializer_class()


Пример с ModelViewSet:
class MyViewSet(MultiSerializerViewSetMixin, ModelViewSet):
    queryset = My.objects.all()
    serializer_class = MySerializer
    serializer_action_classes = {
        'list': MyGetSerializer,
        'create': MySerializer,
        'retrieve': MyGetSerializer,
        'update': MySerializer,
        'partial_update': MySerializer,
        # etc.
    }

Соответственно, к примеру, MySerializer - стандартный вариант сериализера, а MyGetSerializer - полон развёрнутых связанных сущностей, вычисляемых кастомных полей и прочих чудес, облегчающих труд фронтендщика...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы