Home > Software design >  Django / Django Rest Framework ModelViewSet: __init__() takes 1 positional argument but 2 were given
Django / Django Rest Framework ModelViewSet: __init__() takes 1 positional argument but 2 were given

Time:06-24

I'm trying to create a custom "list" under OptionViewSet but It's giving me an error.

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)

Error

__init__() takes 1 positional argument but 2 were given

This works fine:

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']

full traceback

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

CodePudding user response:

The viewsets.ModelViewSet provides the complete set of create/list/retrieve/update/destroy actions by default, If you want a custom list then I believe you should consider Custom ViewSet base classesto customize the behaviour.

Example:

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

Source

So if we modify your Code according to that approach that should look like this;

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)

If you want to extend the ModelViewSet then you can follow the docs related to Marking extra actions for routing. According to that approach OptionViewSet should be like this:

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)

CodePudding user response:

In the url.py, in the the specific path from urlpatters[] you need to call your views.OptionViewSet.as_view() as a middle parameter between the URL path and the name reference:

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

Django has very good documentation and you can read more about the Django-Rest-Framework's ViewSets here: https://www.django-rest-framework.org/api-guide/viewsets/

  • Related