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.
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.
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.
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.