Django / Django Rest Framework ModelViewSet: __init__() принимает 1 позиционный аргумент, но было задано 2

Я пытаюсь создать пользовательский "список" в OptionViewSet, но он выдает ошибку.

class OptionViewSet(viewsets.ModelViewSet):
    serializer_class = OptionSerializer
    queryset = Option.objects.all()

    def list(self, request):
        queryset = Option.objects.all()
        serializer = OptionSerializer(queryset, many=True)
        return Response(serializer.data)

Ошибка

__init__() takes 1 positional argument but 2 were given

Это работает нормально:

class OptionViewSet(viewsets.ModelViewSet):
    serializer_class = OptionSerializer
    queryset = Option.objects.all()

urls.py

path('api/shipping/', include((shipping_routes.urls, 'shipping'), namespace='shipping')),

routes.py

routes.register(r'option', OptionViewSet, basename='option')

serializer

class OptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Option
        fields = ['id', 'extra', 'name']

полное отслеживание

Traceback (most recent call last):
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\Simon\Documents\GitHub\crud-react-django\django_backend\shipping\views.py", line 18, in list
    return Response(serializer.data)

Exception Type: TypeError at /api/shipping/option/
Exception Value: __init__() takes 1 positional argument but 2 were given

В url.py, в конкретном пути из urlpatters[] вам нужно вызвать ваш views.OptionViewSet.as_view() как средний параметр между URL путем и ссылкой на имя:

path('api/shipping/', include((shipping_routes.urls, 'shipping'), namespace='shipping')),

Django имеет очень хорошую документацию, и вы можете прочитать больше о ViewSets в Django-Rest-Framework здесь: https://www.django-rest-framework.org/api-guide/viewsets/

По умолчанию viewsets.ModelViewSet предоставляет полный набор действий create/list/retrieve/update/destroy, если вам нужен пользовательский список, то я считаю, что вам следует рассмотреть базовые классы Custom ViewSet для настройки поведения.

Пример:

from rest_framework import mixins

class CreateListRetrieveViewSet(mixins.CreateModelMixin,
                                mixins.ListModelMixin,
                                mixins.RetrieveModelMixin,
                                viewsets.GenericViewSet):
    """
    A viewset that provides `retrieve`, `create`, and `list` actions.

    To use it, override the class and set the `.queryset` and
    `.serializer_class` attributes.
    """
    pass

Источник

Итак, если мы изменим ваш код в соответствии с этим подходом, то он должен выглядеть следующим образом;

class OptionViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    serializer_class = OptionSerializer
    queryset = Option.objects.all()

    def list(self, request):
        queryset = Option.objects.all()
        serializer = OptionSerializer(queryset, many=True)
        return Response(serializer.data)

Если вы хотите расширить ModelViewSet, то вы можете следовать документации, относящейся к Маркировка дополнительных действий для маршрутизации. Согласно этому подходу OptionViewSet должен выглядеть следующим образом:

class OptionViewSet(viewsets.ModelViewSet):
    serializer_class = OptionSerializer
    queryset = Option.objects.all()
    
    # ... 
    @action(detail=False, methods=['get'])
    def custom_list(self, request):
        queryset = Option.objects.all()
        serializer = OptionSerializer(queryset, many=True)
        return Response(serializer.data)

Я неправильно импортировал Response. Импортировал его из "requests" вместо "rest_framework.response".

Вернуться на верх