Почему этот простой сериализатор Django Rest Framework не работает с ViewSet?

У меня есть конечные точки с Django REST: ProductViewSet и DeviceViewSet. Они просты, как метод GET с retrieve и list.

В то время как я занимался профилированием, я провел небольшое исследование и решил написать свои собственные очень простые сериализаторы (не из DRF), и производительность значительно улучшилась.

Метод ProductViewSet прекрасно работает для методов retrieve и list.

DeviceViewSet работает для list, но не работает для retrieve из-за сериализатора.

Это ошибка:

Traceback (most recent call last):
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/django/template/response.py", line 106, in render
    self.content = self.rendered_content
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/rest_framework/renderers.py", line 723, in render
    context = self.get_context(data, accepted_media_type, renderer_context)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/rest_framework/renderers.py", line 655, in get_context
    raw_data_put_form = self.get_raw_data_form(data, view, 'PUT', request)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/rest_framework/renderers.py", line 551, in get_raw_data_form
    serializer = view.get_serializer(instance=instance)
  File "/home/everton/.virtualenvs/venv/lib/python3.8/site-packages/rest_framework/generics.py", line 110, in get_serializer
    return serializer_class(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'instance'

Все почти идентично, за исключением того, что DeviceSerializer использует ProductSerializer из-за поля ForeignKey. Я не могу найти проблему, какие-нибудь мысли?

Я уже пытался перезаписать методы get_serializer и get_serializer_class и после установки точки останова прямо перед возвратом ответа, сериализованные данные в порядке, ошибка происходит, когда возвращается ответ.

class DeviceViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = models.Device.objects.all()
    serializer_class = DeviceSerializer
    permission_classes = (IsAuthenticated, )

    def get_queryset(self):
        return self.queryset

    def retrieve(self, request, pk=None):
        device = get_object_or_404(self.get_queryset(), id=pk)
        serializer = self.serializer_class(device)
        return Response(data=serializer.data)

    def list(self, request):
        qs = self.get_queryset()
        serializer = self.serializer_class(data=qs, many=True)
        return Response(serializer.data)


class ProductViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = models.Product.objects.all()
    serializer_class = ProductSerializer
    permission_classes = (IsAuthenticated, )

    def get_queryset(self):
        return self.queryset

    def retrieve(self, request, pk=None):
        product = get_object_or_404(self.get_queryset(), id=pk)
        serializer = self.serializer_class(product)
        return Response(data=serializer.data)

    def list(self, request):
        qs = self.get_queryset()
        serializer = self.serializer_class(data=qs, many=True)
        return Response(serializer.data)
class DeviceSerializer(object):
    """
    Serializer for one or more device(s)
    """

    product = ProductSerializer

    def __init__(self, entries, many=False):
        self.many = many
        self.entries = entries if self.many else [entries]

    @property
    def data(self):
        return self.serializer_data(self.entries)

    def serializer_data(self, entries):

        serialized = [
            {
                "id": obj.id,
                "name": obj.name,
                'description': obj.description,
                'product': self.product(obj.product).data,
            } for obj in entries
        ]

        return serialized if self.many else serialized[0]


class ProductSerializer(object):
    """
    Main serializer for products
    """

    def __init__(self, entries, many=False, fields=None, exclude=None):
        self.many = many
        self.entries = entries if self.many else [entries]

    @property
    def data(self):
        return self.serializer_data(self.entries)

    def serializer_data(self, entries):
        serialized = [
            {
                "id": obj.id,
                "productName": obj.product_name,
                "productType": obj.product_type,
                "productSeries": obj.product_series,
            } for obj in entries
        ]

        return serialized if self.many else serialized[0]
Вернуться на верх