5.7 KiB
Routers
Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code.
Some Web frameworks such as Rails provide functionality for automatically determining how the URLs for an application should be mapped to the logic that deals with handling incoming requests.
REST framework adds support for automatic URL routing to Django, and provides you with a simple, quick and consistent way of wiring your view logic to a set of URLs.
Usage
Here's an example of a simple URL conf, that uses DefaultRouter
.
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
There are two mandatory arguments to the register()
method:
prefix
- The URL prefix to use for this set of routes.viewset
- The viewset class.
Optionally, you may also specify an additional argument:
base_name
- The base to use for the URL names that are created. If unset the basename will be automatically generated based on themodel
orqueryset
attribute on the viewset, if it has one.
The example above would generate the following URL patterns:
- URL pattern:
^users/$
Name:'user-list'
- URL pattern:
^users/{pk}/$
Name:'user-detail'
- URL pattern:
^accounts/$
Name:'account-list'
- URL pattern:
^accounts/{pk}/$
Name:'account-detail'
Extra link and actions
Any methods on the viewset decorated with @link
or @action
will also be routed.
For example, a given method like this on the UserViewSet
class:
@action(permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
The following URL pattern would additionally be generated:
- URL pattern:
^users/{pk}/set_password/$
Name:'user-set-password'
API Guide
SimpleRouter
This router includes routes for the standard set of list
, create
, retrieve
, update
, partial_update
and destroy
actions. The viewset can also mark additional methods to be routed, using the @link
or @action
decorators.
URL Style | HTTP Method | Action | URL Name |
---|---|---|---|
{prefix}/ | GET | list | {basename}-list |
POST | create | ||
{prefix}/{lookup}/ | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/ | GET | @link decorated method | {basename}-{methodname} |
POST | @action decorated method |
DefaultRouter
This router is similar to SimpleRouter
as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional .json
style format suffixes.
URL Style | HTTP Method | Action | URL Name |
---|---|---|---|
[.format] | GET | automatically generated root view | api-root |
{prefix}/[.format] | GET | list | {basename}-list |
POST | create | ||
{prefix}/{lookup}/[.format] | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/[.format] | GET | @link decorated method | {basename}-{methodname} |
POST | @action decorated method |
Custom Routers
Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specfic requirements about how the your URLs for your API are strutured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.
The simplest way to implement a custom router is to subclass one of the existing router classes. The .routes
attribute is used to template the URL patterns that will be mapped to each viewset.
Example
The following example will only route to the list
and retrieve
actions, and unlike the routers included by REST framework, it does not use the trailing slash convention.
class ReadOnlyRouter(SimpleRouter):
"""
A router for read-only APIs, which doesn't use trailing suffixes.
"""
routes = [
(r'^{prefix}$', {'get': 'list'}, '{basename}-list'),
(r'^{prefix}/{lookup}$', {'get': 'retrieve'}, '{basename}-detail')
]
Advanced custom routers
If you want to provide totally custom behavior, you can override BaseRouter
and override the get_urls(self)
method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the self.registry
attribute.
You may also want to override the get_default_base_name(self, viewset)
method, or else always explicitly set the base_name
argument when registering your viewsets with the router.