Django REST Framework API Guide (1) : Requesting Django REST Framework API Guide (2) : Responding to Django REST Framework API Guide (3) : Views Django REST Framework API Guide (4) : Generic Views Django REST Framework API Guide (5) : View Sets Django REST Framework API Guide (6) : Routing Django REST Framework API Guide (7) : Parsing

Link to official text

routing

Some Web frameworks, such as Rails, provide a way to automatically determine how an application’s URL maps to processing requests.

The REST Framework adds support for Django’s automatic URL routing and provides a simple, efficient, and consistent way to connect view logic to a set of urls.

usage

Here is an example of a simple URL configuration using SimpleRouter.

from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
Copy the code

The register() method takes two mandatory arguments:

  • prefix– Sets the prefix of the route group.
  • viewset– Sets the corresponding view set class.

Alternatively, you can specify an additional argument:

  • base_name– The base of the URL name used to create. If not, it will be based on the view setquerysetProperties are automatically generated. Note if the view set does not containquerysetProperty must be set when the view set is registeredbase_name.

The above example generates the following URL schema:

  • 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'

Note: The base_name parameter is used to specify the initial part of the view name schema. In the example above, the User or Account section.

In general, you do not need to specify the base_name parameter, but if you have a view set that defines a custom get_querySet method, the view set may not have the.querySet attribute set. If you try to register the view at this point, you will see an error like this:

'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
Copy the code

The ‘base_name’ parameter is not specified, and the name in the view cannot be automatically determined because it does not have the ‘.queryset’ attribute.

In this case, you need to explicitly set the base_name parameter when registering the view set, because it cannot be automatically determined from the model name.

useincludeWith routing

The.urls property on a routing instance is a standard URL pattern. There are many different styles of how to include these urls.

For example, you could append router.urls to a list of existing views…

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
]

urlpatterns += router.urls
Copy the code

Alternatively, you can use Django’s include functions, such as…

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^', include(router.urls)),
]
Copy the code

You can also set a namespace.

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include(router.urls, namespace='api')),]Copy the code

If you use a namespace for the hyperlink serializer, you also need to ensure that any view_name arguments on the serializer correctly reflect the namespace. In the example above, you need to include parameters such as view_name=’ API :user-detail’ for the serializer field that is hyperlinked to the user details view.

Additional links and actions

Any methods on views decorated with @detail_route or @list_route will also be routed. For example, given a method like this in the UserViewSet class:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):.    @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None):.Copy the code

The following URL schema is generated:

  • URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password'

If you do not want to use the default generated URL schema, you can customize it using the URl_path parameter.

For example, if you wanted to change the URL of our custom action to ^users/{pk}/change-password/$, you could write:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):.    @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')
    def set_password(self, request, pk=None):.Copy the code

The above example will now generate the following URL schema:

  • URL pattern: ^users/{pk}/change-password/$ Name: 'user-change-password'

If you do not want to use the generated default name, you can customize it using the URl_name parameter.

For example, if you wanted to change the name of a custom action to ‘user-change-password’, you could write:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):.    @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')
    def set_password(self, request, pk=None):.Copy the code

The above example will now generate the following URL schema:

  • URL pattern: ^users/{pk}/set_password/$ Name: 'user-change-password'

You can use both the url_path and url_name parameters.

For more information, see View Set: Marking additional routing behavior.

API reference

SimpleRouter

SimpleRouter contains the standard List, Create, Retrieve, UPDATE, Partial_UPDATE, and destroy Actions. SimpleRouter also supports view sets that use the @detail_route or @list_route decorator to mark other methods to route.

URL Style HTTP Method Action URL Name
{prefix}/ GET list {basename}-list
POST create
{prefix}/{methodname}/ GET, or specified by the ‘methods’ parameter ‘@list_route’ method of decoration {basename}-{methodname}
{prefix}/{lookup}/ GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{methodname}/ GET, or specified by the ‘methods’ parameter ‘@detail_route’ decorates the method {basename}-{methodname}

By default, urls created by SimpleRouter attach trailing slashes. You can modify this behavior by setting the trailing_slash parameter to False when instantiating the router. Such as:

router = SimpleRouter(trailing_slash=False)
Copy the code

Trailing slashes are standard in Django, but not by default in some other frameworks, such as Rails. Choosing which style to use is largely a matter of preference, although some JavaScript frameworks may expect a specific routing style.

SimpleRouter will match the value of a lookup containing any characters other than the slash and period characters. For stricter (or looser) lookup patterns, set the lookup_value_regex property on the view set. For example, you can limit a lookup to a valid UUID:

class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    lookup_field = 'my_model_id'
    lookup_value_regex = '[0-9a-f]{32}'
Copy the code

DefaultRouter

DefaultRouter is similar to SimpleRouter above, but also contains a default API root view that returns a response containing hyperlinks to all 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}/{methodname}/[.format] GET, or specified by the ‘methods’ parameter ‘@list_route’ method of decoration {basename}-{methodname}
{prefix}/{lookup}/[.format] GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{methodname}/[.format] GET, or specified by the ‘methods’ parameter ‘@detail_route’ decorates the method {basename}-{methodname}

{prefix}/[. Format]/ style is 404. I don’t know if it’s a problem or an official update.

As with SimpleRouter, you can remove trailing slashes on the URL path by setting the trailing_slash parameter to False when instantiating DefaultRouter.

router = DefaultRouter(trailing_slash=False)
Copy the code

Custom Route

Custom routing is not something you need to do very often, but it can be useful if you have specific requirements for how the API urls are constructed. Doing so allows you to encapsulate the URL structure in a reusable way, ensuring that you don’t have to explicitly write a URL schema for every new view.

The easiest way to implement custom routing is to subclass one of the existing routing classes. The.routes attribute is used to templatethe URL pattern that will be mapped to each view set. The.routes attribute is a list of Routes (Route is a namedtuple).

Route named tuple parameter:

Url: A string representing the URL to be routed. Can contain the following format strings:

  • {prefix}– Indicates the URL prefix of the route.
  • {lookup}– Matches the lookup field of a single instance.
  • {trailing_slash}– Can be a ‘/’ or an empty string, dependingtrailing_slashParameters.

Mapping: Indicates the mapping between HTTP method names and view methods

Name: The name of the URL used to call reverse. May contain the following format strings:

  • {basename}– Creates the base of the URL name.

Initkwargs: dictionary of any other parameters that should be passed when instantiating the view. Note that the suffix parameter is reserved to identify the view set type and is used when generating view names and breadcrumb links.

User-defined dynamic routes

You can also customize the routing of @list_route and @detail_route decorators. To route one or both of these decorators, include a DynamicListRoute and/or DynamicDetailRoute (don’t forget type namedtuple) in the.routes list.

The parameters of DynamicListRoute and DynamicDetailRoute are:

Url: A string representing the URL to be routed. You can contain the same format string as Route and also accept strings in the {methodName} and {methodNamehyphen} formats.

Name: The name used when reverse is called. It can contain the following format strings: {basename}, {methodName}, and {methodNamehyphen}.

Initkwargs: dictionary of any other parameters that should be passed when instantiating the view.

Take a chestnut

The following example routes only the List and retrieve Action and does not use the trailing slash convention.

from rest_framework.routers import Route, DynamicDetailRoute, 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',
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}$',
            mapping={'get': 'retrieve'},
            name='{basename}-detail',
            initkwargs={'suffix': 'Detail'}
        ),
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodnamehyphen}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        )
    ]
Copy the code

Let’s look at the route that CustomReadOnlyRouter generates for a simple set of views.

Views. Py:

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """ A viewset that provides the standard actions """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'username'

    @detail_route()
    def group_names(self, request, pk=None):
        """ Returns a list of all the group names that the given user belongs to. """
        user = self.get_object()
        groups = user.groups.all()
        return Response([group.name for group in groups])
Copy the code

Urls. Py:

router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = router.urls
Copy the code

The following mapping will be generated…

URL HTTP Method Action URL Name
/users GET list user-list
/users/{username} GET retrieve user-detail
/users/{username}/group-names GET group_names user-group-names

For another example of setting the.routes attribute, see the source code for the SimpleRouter class.

Advanced custom router

If you want to provide fully custom behavior, you can extend BaseRouter and override the get_urls(self) method. This method should check the registered set of views and return a set of URL patterns. The registered prefix, ViewSet, and Basename tuples can be checked by accessing the self.registry property.

You might also want to override the get_default_base_name (self, viewset) method, or always explicitly set the base_name parameter when registering the viewset with the route.

Third-party Software Packages

The following are the third-party packages available.

DRF Nested Routers

ModelRouter (wq.db.rest)

DRF-extensions