mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-28 13:54:28 +03:00
Add support for action and link routing
This commit is contained in:
parent
c785628300
commit
fb41d2ac8f
|
@ -12,13 +12,26 @@ Let's take our current set of views, and refactor them into view sets.
|
||||||
|
|
||||||
First of all let's refactor our `UserListView` and `UserDetailView` views into a single `UserViewSet`. We can remove the two views, and replace then with a single class:
|
First of all let's refactor our `UserListView` and `UserDetailView` views into a single `UserViewSet`. We can remove the two views, and replace then with a single class:
|
||||||
|
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
class UserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""
|
||||||
|
This viewset automatically provides `list` and `detail` actions.
|
||||||
|
"""
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
|
|
||||||
Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighlight` view classes. We can remove the three views, and again replace them with a single class.
|
Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighlight` view classes. We can remove the three views, and again replace them with a single class.
|
||||||
|
|
||||||
|
from rest_framework import viewsets
|
||||||
|
from rest_framework.decorators import link
|
||||||
|
|
||||||
class SnippetViewSet(viewsets.ModelViewSet):
|
class SnippetViewSet(viewsets.ModelViewSet):
|
||||||
|
"""
|
||||||
|
This viewset automatically provides `list`, `create`, `retrieve`,
|
||||||
|
`update` and `destroy` actions.
|
||||||
|
|
||||||
|
Additionally we provide an extra `highlight` action, by using the
|
||||||
|
`@link` decorator.
|
||||||
|
"""
|
||||||
queryset = Snippet.objects.all()
|
queryset = Snippet.objects.all()
|
||||||
serializer_class = SnippetSerializer
|
serializer_class = SnippetSerializer
|
||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
|
||||||
|
|
|
@ -97,3 +97,25 @@ def permission_classes(permission_classes):
|
||||||
func.permission_classes = permission_classes
|
func.permission_classes = permission_classes
|
||||||
return func
|
return func
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def link(**kwargs):
|
||||||
|
"""
|
||||||
|
Used to mark a method on a ViewSet that should be routed for GET requests.
|
||||||
|
"""
|
||||||
|
def decorator(func):
|
||||||
|
func.bind_to_method = 'get'
|
||||||
|
func.kwargs = kwargs
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def action(**kwargs):
|
||||||
|
"""
|
||||||
|
Used to mark a method on a ViewSet that should be routed for POST requests.
|
||||||
|
"""
|
||||||
|
def decorator(func):
|
||||||
|
func.bind_to_method = 'post'
|
||||||
|
func.kwargs = kwargs
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
|
@ -24,10 +24,12 @@ class DefaultRouter(BaseRouter):
|
||||||
(r'$', {'get': 'list', 'post': 'create'}, '%s-list'),
|
(r'$', {'get': 'list', 'post': 'create'}, '%s-list'),
|
||||||
(r'(?P<pk>[^/]+)/$', {'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}, '%s-detail'),
|
(r'(?P<pk>[^/]+)/$', {'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}, '%s-detail'),
|
||||||
]
|
]
|
||||||
|
extra_routes = (r'(?P<pk>[^/]+)/%s/$', '%s-%s')
|
||||||
|
|
||||||
def get_urlpatterns(self):
|
def get_urlpatterns(self):
|
||||||
ret = []
|
ret = []
|
||||||
for prefix, viewset, base_name in self.registry:
|
for prefix, viewset, base_name in self.registry:
|
||||||
|
# Bind standard routes
|
||||||
for suffix, action_mapping, name_format in self.route_list:
|
for suffix, action_mapping, name_format in self.route_list:
|
||||||
|
|
||||||
# Only actions which actually exist on the viewset will be bound
|
# Only actions which actually exist on the viewset will be bound
|
||||||
|
@ -36,8 +38,26 @@ class DefaultRouter(BaseRouter):
|
||||||
if hasattr(viewset, action):
|
if hasattr(viewset, action):
|
||||||
bound_actions[method] = action
|
bound_actions[method] = action
|
||||||
|
|
||||||
|
# Build the url pattern
|
||||||
regex = prefix + suffix
|
regex = prefix + suffix
|
||||||
view = viewset.as_view(bound_actions)
|
view = viewset.as_view(bound_actions)
|
||||||
name = name_format % base_name
|
name = name_format % base_name
|
||||||
ret.append(url(regex, view, name=name))
|
ret.append(url(regex, view, name=name))
|
||||||
|
|
||||||
|
# Bind any extra @action or @link routes
|
||||||
|
for attr in dir(viewset):
|
||||||
|
func = getattr(viewset, attr)
|
||||||
|
http_method = getattr(func, 'bind_to_method', None)
|
||||||
|
if not http_method:
|
||||||
|
continue
|
||||||
|
|
||||||
|
regex_format, name_format = self.extra_routes
|
||||||
|
|
||||||
|
# Build the url pattern
|
||||||
|
regex = regex_format % attr
|
||||||
|
view = viewset.as_view({http_method: attr}, **func.kwargs)
|
||||||
|
name = name_format % (base_name, attr)
|
||||||
|
ret.append(url(regex, view, name=name))
|
||||||
|
|
||||||
|
# Return a list of url patterns
|
||||||
return ret
|
return ret
|
||||||
|
|
Loading…
Reference in New Issue
Block a user