aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2013-04-04 20:35:40 +0100
committerTom Christie2013-04-04 20:35:40 +0100
commitfb41d2ac8f495ae0728e3f38c6a21306f0507316 (patch)
tree8dc1c7acb4778b900eaef144bd2e1857216d72a1
parentc785628300d2b7cce63862a18915c537f8a3ab24 (diff)
downloaddjango-rest-framework-fb41d2ac8f495ae0728e3f38c6a21306f0507316.tar.bz2
Add support for action and link routing
-rw-r--r--docs/tutorial/6-viewsets-and-routers.md15
-rw-r--r--rest_framework/decorators.py22
-rw-r--r--rest_framework/routers.py20
3 files changed, 56 insertions, 1 deletions
diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md
index 9c8a218f..8a2108b3 100644
--- a/docs/tutorial/6-viewsets-and-routers.md
+++ b/docs/tutorial/6-viewsets-and-routers.md
@@ -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:
- class UserViewSet(viewsets.ModelViewSet):
+ class UserViewSet(viewsets.ReadOnlyModelViewSet):
+ """
+ This viewset automatically provides `list` and `detail` actions.
+ """
queryset = User.objects.all()
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.
+ from rest_framework import viewsets
+ from rest_framework.decorators import link
+
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()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py
index 8250cd3b..00b37f8b 100644
--- a/rest_framework/decorators.py
+++ b/rest_framework/decorators.py
@@ -97,3 +97,25 @@ def permission_classes(permission_classes):
func.permission_classes = permission_classes
return func
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
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index 63eae5d7..d1e96156 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -24,10 +24,12 @@ class DefaultRouter(BaseRouter):
(r'$', {'get': 'list', 'post': 'create'}, '%s-list'),
(r'(?P<pk>[^/]+)/$', {'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}, '%s-detail'),
]
+ extra_routes = (r'(?P<pk>[^/]+)/%s/$', '%s-%s')
def get_urlpatterns(self):
ret = []
for prefix, viewset, base_name in self.registry:
+ # Bind standard routes
for suffix, action_mapping, name_format in self.route_list:
# Only actions which actually exist on the viewset will be bound
@@ -36,8 +38,26 @@ class DefaultRouter(BaseRouter):
if hasattr(viewset, action):
bound_actions[method] = action
+ # Build the url pattern
regex = prefix + suffix
view = viewset.as_view(bound_actions)
name = name_format % base_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