Document extra action method mapping

This commit is contained in:
Ryan P Kilby 2018-06-25 15:50:21 -04:00
parent f32398953d
commit d1676f999b
2 changed files with 35 additions and 8 deletions

View File

@ -398,10 +398,15 @@ A string representing the function that should be used when generating view name
This should be a function with the following signature: This should be a function with the following signature:
view_name(cls, suffix=None) view_name(self)
* `cls`: The view class. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing `cls.__name__`. * `self`: The view instance. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing `self.__class__.__name__`.
* `suffix`: The optional suffix used when differentiating individual views in a viewset.
If the view instance inherits `ViewSet`, it may have been initialized with several optional arguments:
* `name`: A name expliticly provided to a view in the viewset. Typically, this value should be used as-is when provided.
* `suffix`: Text used when differentiating individual views in a viewset. This argument is mutually exclusive to `name`.
* `detail`: Boolean that differentiates an individual view in a viewset as either being a 'list' or 'detail' view.
Default: `'rest_framework.views.get_view_name'` Default: `'rest_framework.views.get_view_name'`
@ -413,11 +418,15 @@ This setting can be changed to support markup styles other than the default mark
This should be a function with the following signature: This should be a function with the following signature:
view_description(cls, html=False) view_description(self, html=False)
* `cls`: The view class. Typically the description function would inspect the docstring of the class when generating a description, by accessing `cls.__doc__` * `self`: The view instance. Typically the description function would inspect the docstring of the class when generating a description, by accessing `self.__class__.__doc__`
* `html`: A boolean indicating if HTML output is required. `True` when used in the browsable API, and `False` when used in generating `OPTIONS` responses. * `html`: A boolean indicating if HTML output is required. `True` when used in the browsable API, and `False` when used in generating `OPTIONS` responses.
If the view instance inherits `ViewSet`, it may have been initialized with several optional arguments:
* `description`: A description explicitly provided to the view in the viewset. Typically, this is set by extra viewset `action`s, and should be used as-is.
Default: `'rest_framework.views.get_view_description'` Default: `'rest_framework.views.get_view_description'`
## HTML Select Field cutoffs ## HTML Select Field cutoffs

View File

@ -110,6 +110,8 @@ During dispatch, the following attributes are available on the `ViewSet`.
* `action` - the name of the current action (e.g., `list`, `create`). * `action` - the name of the current action (e.g., `list`, `create`).
* `detail` - boolean indicating if the current action is configured for a list or detail view. * `detail` - boolean indicating if the current action is configured for a list or detail view.
* `suffix` - the display suffix for the viewset type - mirrors the `detail` attribute. * `suffix` - the display suffix for the viewset type - mirrors the `detail` attribute.
* `name` - the display name for the viewset. This argument is mutually exclusive to `suffix`.
* `description` - the display description for the individual view of a viewset.
You may inspect these attributes to adjust behaviour based on the current action. For example, you could restrict permissions to everything except the `list` action similar to this: You may inspect these attributes to adjust behaviour based on the current action. For example, you could restrict permissions to everything except the `list` action similar to this:
@ -142,7 +144,7 @@ A more complete example of extra actions:
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
@action(methods=['post'], detail=True) @action(detail=True, methods=['post'])
def set_password(self, request, pk=None): def set_password(self, request, pk=None):
user = self.get_object() user = self.get_object()
serializer = PasswordSerializer(data=request.data) serializer = PasswordSerializer(data=request.data)
@ -168,13 +170,13 @@ A more complete example of extra actions:
The decorator can additionally take extra arguments that will be set for the routed view only. For example: The decorator can additionally take extra arguments that will be set for the routed view only. For example:
@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf]) @action(detail=True, methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None): def set_password(self, request, pk=None):
... ...
These decorator will route `GET` requests by default, but may also accept other HTTP methods by setting the `methods` argument. For example: These decorator will route `GET` requests by default, but may also accept other HTTP methods by setting the `methods` argument. For example:
@action(methods=['post', 'delete'], detail=True) @action(detail=True, methods=['post', 'delete'])
def unset_password(self, request, pk=None): def unset_password(self, request, pk=None):
... ...
@ -182,6 +184,22 @@ The two new actions will then be available at the urls `^users/{pk}/set_password
To view all extra actions, call the `.get_extra_actions()` method. To view all extra actions, call the `.get_extra_actions()` method.
### Routing additional HTTP methods for extra actions
Extra actions can be mapped to different `ViewSet` methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments.
```python
@action(detail=True, methods=['put'], name='Change Password')
def password(self, request, pk=None):
"""Update the user's password."""
...
@password.mapping.delete
def delete_password(self, request, pk=None):
"""Delete the user's password."""
...
```
## Reversing action URLs ## Reversing action URLs
If you need to get the URL of an action, use the `.reverse_action()` method. This is a convenience wrapper for `reverse()`, automatically passing the view's `request` object and prepending the `url_name` with the `.basename` attribute. If you need to get the URL of an action, use the `.reverse_action()` method. This is a convenience wrapper for `reverse()`, automatically passing the view's `request` object and prepending the `url_name` with the `.basename` attribute.