Почему этот простой сериализатор 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]