djangodjango-rest-frameworkdjango-serializerdjango-rest-viewsets

Django Serializer - `methodViewSet(viewsets.ViewSet)` is not displayed in url list


I am trying to combine multiple serializers into a single API call, and as a result, I am using viewsets.ViewSet. I am aware that viewsets.ModelViewSet automatically generates the routes, but with viewsets.ViewSet, I am not seeing the expected route for my API.

When I switch to viewsets.ModelViewSet, the route becomes available. This makes me think my issue is specific to how viewsets.ViewSet handles routing.

According to the documentation (https://www.django-rest-framework.org/api-guide/viewsets/), I should be able to register the URL like I would with ModelViewSet. However, the route doesn't appear when using viewsets.ViewSet.

Any suggestions on what might be going wrong?

views.py

class MethodViewSet(viewsets.ViewSet):
    permission_classes = [IsAuthenticated]
    authentication_classes = [TokenAuthentication]
    
    @action(detail=False, methods=['get'], url_path='method-path')
    def list(self, request):
...

urls.py

from rest_framework.routers import DefaultRouter
from .views import (
     MethodViewSet,
     )

from rest_framework.authtoken.views import obtain_auth_token

router = DefaultRouter()
...
router.register(r'method-path', MethodViewSet, basename='methodbasename')

Solution

  • It looks like the issue you're facing is due to how viewsets.ViewSet works with DRF's DefaultRouter. Unlike ModelViewSet, ViewSet does not automatically generate the usual CRUD routes (list, create, etc.) for you unless you explicitly define them using @action or custom methods.

    In your case, since you're using viewsets.ViewSet, you need to ensure that your viewset is properly registering actions with the router. You're already using @action, which is correct, but there might be a small issue with the URL configuration in your router.

    Here’s the updated suggestion:

    1. Check @action Method: Make sure your list method is correctly defined with the @action decorator.
    2. Custom Router Configuration: In the DefaultRouter, when registering a ViewSet, you should not use basename unless you have specific requirements. Try removing the basename parameter and registering without it. This allows the router to automatically generate the URL.

    Here’s the updated code:

    views.py

    from rest_framework import viewsets
    from rest_framework.decorators import action
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.authentication import TokenAuthentication
    
    class MethodViewSet(viewsets.ViewSet):
        permission_classes = [IsAuthenticated]
        authentication_classes = [TokenAuthentication]
        
        @action(detail=False, methods=['get'], url_path='method-path')
        def list(self, request):
            # your code here
            pass
    

    urls.py

    from rest_framework.routers import DefaultRouter
    from .views import MethodViewSet
    from rest_framework.authtoken.views import obtain_auth_token
    
    router = DefaultRouter()
    router.register(r'method-path', MethodViewSet)
    
    # Add this to your urlpatterns to include the router
    urlpatterns = [
        ...  # your other url patterns
        path('', include(router.urls)),  # Ensure this line is present
    ]
    

    Key Points:

    After this, the route for method-path/ should appear and should be accessible.

    Let me know if that resolves your issue!