How to hook up DRF ModelViewset to the app's root

Question:

I have a small django app with a single ViewSet that extends DRF’s ModelViewSet. I’ve tried attaching it to the app’s root url like so

urlpatterns = [
    path(r"", NotificationViewSet.as_view(), name="company"),
]

But this is causing an error:

TypeError: The actions argument must be provided when calling .as_view() on a ViewSet. For example .as_view({'get': 'list'})

The error is helpful enough to show how to map the get method and github copilot suggests:

urlpatterns = [
    path(
        r"",
        NotificationViewSet.as_view(
            {
                "get": "list",
                "post": "create",
                "patch": "partial_update",
                "delete": "destroy",
            }
        ),
        name="company",
    ),
]

But I’m not sure this is correct. And this doesn’t appear to handle retrieve which would require a URL parameter. I am surprised I have to be so explicit. Surely there is an easier way.

Asked By: kaan_a

||

Answers:

The common way to include all the routes of a ViewSet is by using a router, for example:

...
from django.urls import include, path
from rest_framework import routers
...

router = routers.DefaultRouter()
router.register('', NotificationViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

Also, you can use .as_view() aswell:

urlpatterns = [
    path(
        '',
        NotificationViewSet.as_view(
            {
                "get": "list",
                "post": "create"
            }
        ),
        name="company",
    ),
    path(
        '<int:pk>/',
        NotificationViewSet.as_view(
            {
                "patch": "partial_update",
                "delete": "destroy"
            }
        ),
        name="company-detail",
    ),
]

Notice that we need a dedicated path for methods that requires a pk in the URL, router.register() manages it automatically.

Answered By: Jonathan Quispe