diff options
Diffstat (limited to 'docs/api-guide/routers.md')
| -rw-r--r-- | docs/api-guide/routers.md | 117 | 
1 files changed, 94 insertions, 23 deletions
| diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 64f05af3..2d760ca4 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -51,36 +51,41 @@ This means you'll need to explicitly set the `base_name` argument when registeri  ### Extra link and actions -Any methods on the viewset decorated with `@link` or `@action` will also be routed. +Any methods on the viewset decorated with `@detail_route` or `@list_route` will also be routed.  For example, given a method like this on the `UserViewSet` class: -	from myapp.permissions import IsAdminOrIsSelf -    from rest_framework.decorators import action - -    @action(permission_classes=[IsAdminOrIsSelf]) -    def set_password(self, request, pk=None): +    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): +            ...  The following URL pattern would additionally be generated:  * URL pattern: `^users/{pk}/set_password/$`  Name: `'user-set-password'` +For more information see the viewset documentation on [marking extra actions for routing][route-decorators]. +  # 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. +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 `@detail_route` or `@list_route` decorators.  <table border=1>      <tr><th>URL Style</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr>      <tr><td rowspan=2>{prefix}/</td><td>GET</td><td>list</td><td rowspan=2>{basename}-list</td></tr></tr>      <tr><td>POST</td><td>create</td></tr> +    <tr><td>{prefix}/{methodname}/</td><td>GET, or as specified by `methods` argument</td><td>`@list_route` decorated method</td><td>{basename}-{methodname}</td></tr>      <tr><td rowspan=4>{prefix}/{lookup}/</td><td>GET</td><td>retrieve</td><td rowspan=4>{basename}-detail</td></tr></tr>      <tr><td>PUT</td><td>update</td></tr>      <tr><td>PATCH</td><td>partial_update</td></tr>      <tr><td>DELETE</td><td>destroy</td></tr> -    <tr><td rowspan=2>{prefix}/{lookup}/{methodname}/</td><td>GET</td><td>@link decorated method</td><td rowspan=2>{basename}-{methodname}</td></tr> -    <tr><td>POST</td><td>@action decorated method</td></tr> +    <tr><td>{prefix}/{lookup}/{methodname}/</td><td>GET, or as specified by `methods` argument</td><td>`@detail_route` decorated method</td><td>{basename}-{methodname}</td></tr>  </table>  By default the URLs created by `SimpleRouter` are appended with a trailing slash. @@ -90,6 +95,12 @@ This behavior can be modified by setting the `trailing_slash` argument to `False  Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails.  Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style. +The router will match lookup values containing any characters except slashes and period characters.  For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset.  For example, you can limit the lookup to valid UUIDs: + +    class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): +        lookup_field = 'my_model_id' +        lookup_value_regex = '[0-9a-f]{32}' +  ## 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. @@ -99,12 +110,12 @@ This router is similar to `SimpleRouter` as above, but additionally includes a d      <tr><td>[.format]</td><td>GET</td><td>automatically generated root view</td><td>api-root</td></tr></tr>      <tr><td rowspan=2>{prefix}/[.format]</td><td>GET</td><td>list</td><td rowspan=2>{basename}-list</td></tr></tr>      <tr><td>POST</td><td>create</td></tr> +    <tr><td>{prefix}/{methodname}/[.format]</td><td>GET, or as specified by `methods` argument</td><td>`@list_route` decorated method</td><td>{basename}-{methodname}</td></tr>      <tr><td rowspan=4>{prefix}/{lookup}/[.format]</td><td>GET</td><td>retrieve</td><td rowspan=4>{basename}-detail</td></tr></tr>      <tr><td>PUT</td><td>update</td></tr>      <tr><td>PATCH</td><td>partial_update</td></tr>      <tr><td>DELETE</td><td>destroy</td></tr> -    <tr><td rowspan=2>{prefix}/{lookup}/{methodname}/[.format]</td><td>GET</td><td>@link decorated method</td><td rowspan=2>{basename}-{methodname}</td></tr> -    <tr><td>POST</td><td>@action decorated method</td></tr> +    <tr><td>{prefix}/{lookup}/{methodname}/[.format]</td><td>GET, or as specified by `methods` argument</td><td>`@detail_route` decorated method</td><td>{basename}-{methodname}</td></tr>  </table>  As with `SimpleRouter` the trailing slashes on the URL routes can be removed by setting the `trailing_slash` argument to `False` when instantiating the router. @@ -133,28 +144,87 @@ The arguments to the `Route` named tuple are:  **initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view.  Note that the `suffix` argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links. +## Customizing dynamic routes + +You can also customize how the `@list_route` and `@detail_route` decorators are routed. +To route either or both of these decorators, include a `DynamicListRoute` and/or `DynamicDetailRoute` named tuple in the `.routes` list. + +The arguments to `DynamicListRoute` and `DynamicDetailRoute` are: + +**url**: A string representing the URL to be routed. May include the same format strings as `Route`, and additionally accepts the `{methodname}` and `{methodnamehyphen}` format strings. + +**name**: The name of the URL as used in `reverse` calls. May include the following format strings: `{basename}`, `{methodname}` and `{methodnamehyphen}`. + +**initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. +  ## Example  The following example will only route to the `list` and `retrieve` actions, and does not use the trailing slash convention. -    from rest_framework.routers import Route, SimpleRouter +    from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter -    class ReadOnlyRouter(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'}) +            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={} +        	)          ] -The `SimpleRouter` class provides another example of setting the `.routes` attribute. +Let's take a look at the routes our `CustomReadOnlyRouter` would generate for a simple viewset. + +`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): +            """ +            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]) + +`urls.py`: + +    router = CustomReadOnlyRouter() +    router.register('users', UserViewSet) +	urlpatterns = router.urls + +The following mappings would be generated... + +<table border=1> +    <tr><th>URL</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr> +    <tr><td>/users</td><td>GET</td><td>list</td><td>user-list</td></tr> +    <tr><td>/users/{username}</td><td>GET</td><td>retrieve</td><td>user-detail</td></tr> +    <tr><td>/users/{username}/group-names</td><td>GET</td><td>group_names</td><td>user-group-names</td></tr> +</table> + +For another example of setting the `.routes` attribute, see the source code for the `SimpleRouter` class.  ## Advanced custom routers @@ -184,6 +254,7 @@ The [wq.db package][wq.db] provides an advanced [Router][wq.db-router] class (an  The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions-routers] for creating [nested viewsets][drf-extensions-nested-viewsets], [collection level controllers][drf-extensions-collection-level-controllers] with [customizable endpoint names][drf-extensions-customizable-endpoint-names].  [cite]: http://guides.rubyonrails.org/routing.html +[route-decorators]: viewsets.html#marking-extra-actions-for-routing  [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers  [wq.db]: http://wq.io/wq.db  [wq.db-router]: http://wq.io/docs/app.py @@ -191,4 +262,4 @@ The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions  [drf-extensions-routers]: http://chibisov.github.io/drf-extensions/docs/#routers  [drf-extensions-nested-viewsets]: http://chibisov.github.io/drf-extensions/docs/#nested-routes  [drf-extensions-collection-level-controllers]: http://chibisov.github.io/drf-extensions/docs/#collection-level-controllers -[drf-extensions-customizable-endpoint-names]: http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name
\ No newline at end of file +[drf-extensions-customizable-endpoint-names]: http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name | 
