Skip to content

Routers ​

When using ViewSets, you don't need to manually design your URLs. DRF routers automatically wire up your view logic to a standard set of RESTful endpoints, keeping your routing incredibly DRY and consistent.

The SimpleRouter ​

The SimpleRouter includes the standard set of routes for list, create, retrieve, update, partial_update and destroy.

python
from rest_framework.routers import SimpleRouter
from . import views

router = SimpleRouter()
router.register(r'users', views.UserViewSet, basename='user')

Registering router.register(r'users', UserViewSet) automatically generates:

URLHTTP MethodAction
/users/GETlist()
/users/POSTcreate()
/users/{pk}/GETretrieve()
/users/{pk}/PUTupdate()
/users/{pk}/PATCHpartial_update()
/users/{pk}/DELETEdestroy()

The DefaultRouter ​

The DefaultRouter is identical to SimpleRouter, but it provides two additional benefits:

  1. It includes an automatic API root view that returns a dictionary mapping of all registered list views.
  2. It generates format suffix patterns (e.g., .json or .html) for all its routes natively, meaning you don't need to manually use format_suffix_patterns in your urls.py.
python
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'users', views.UserViewSet, basename='user')

Adding to urlpatterns ​

There are two primary ways to add your router's generated URLs to your Django urlpatterns.

Using path() and include() ​

You can append the router's .urls property to your URL list using Django's standard path() and include() functions. This is incredibly useful if you want to namespace your API endpoints:

python
from django.urls import path, include

urlpatterns = [
    # Prefixes all router-generated URLs with '/api/v1/'
    path('api/v1/', include(router.urls)),
]

Extending the list natively ​

Since .urls is just a standard list of Django URL patterns, you can simply append it to your existing list without needing include():

python
urlpatterns = [
    path('custom/', custom_view),
]

urlpatterns += router.urls

Extra Actions ​

If you have defined custom endpoints on your ViewSet using the @action decorator, routers will automatically generate URLs for them as well.

python
# In your ViewSet
from rest_framework.decorators import action

class UserViewSet(ModelViewSet):
    # ...
    
    @action(detail=True, methods=['post'])
    def set_password(self, request, pk=None):
        pass # Handle setting the password

The router will recognize this decorator and automatically generate the detail route: /users/{pk}/set_password/.

Custom Routers ​

If you need a routing schema that is fundamentally different from the standard RESTful pattern, you can build a custom router by subclassing BaseRouter or SimpleRouter.

python
from rest_framework.routers import Route, DynamicRoute, SimpleRouter

class CustomReadOnlyRouter(SimpleRouter):
    """
    A router for read-only APIs, which doesn't use trailing slashes.
    """
    routes = [
        Route(
            url=r'^{prefix}$',
            mapping={'get': 'list'},
            name='{basename}-list',
            detail=False,
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}$',
            mapping={'get': 'retrieve'},
            name='{basename}-detail',
            detail=True,
            initkwargs={'suffix': 'Detail'}
        ),
        DynamicRoute(
            url=r'^{prefix}/{lookup}/{url_path}$',
            name='{basename}-{url_name}',
            detail=True,
            initkwargs={}
        )
    ]

Custom routers allow you to explicitly define how your viewset actions map to HTTP methods and URL patterns, bypassing DRF's defaults completely.