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')
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:
@action
Method: Make sure your list
method is correctly defined with the @action
decorator.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
]
basename
parameter is typically needed for ModelViewSet where DRF uses it to generate names for URLs like method-path-list
, method-path-detail
, etc.ViewSet
, since you're defining custom actions with @action
, you don't necessarily need the basename
unless you're doing something special with naming conventions.urlpatterns
.After this, the route for method-path/
should appear and should be accessible.
Let me know if that resolves your issue!