aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/routers.py
diff options
context:
space:
mode:
authorTom Christie2013-04-26 14:59:21 +0100
committerTom Christie2013-04-26 14:59:21 +0100
commit8fa79a7fd38dda015afa658084361c6da2856e46 (patch)
treeef8080a9d24b488402429c0bae101e3f395f1f8b /rest_framework/routers.py
parente301e2d974649a932ab9a7ca32199c068fa30495 (diff)
downloaddjango-rest-framework-8fa79a7fd38dda015afa658084361c6da2856e46.tar.bz2
Deal with List/Instance suffixes for viewsets
Diffstat (limited to 'rest_framework/routers.py')
-rw-r--r--rest_framework/routers.py72
1 files changed, 39 insertions, 33 deletions
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index b7052218..3a8c4508 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -13,6 +13,7 @@ For example, you might have a `urls.py` that looks something like this:
urlpatterns = router.urls
"""
+from collections import namedtuple
from django.conf.urls import url, patterns
from django.db import models
from rest_framework.decorators import api_view
@@ -22,6 +23,9 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework.urlpatterns import format_suffix_patterns
+Route = namedtuple('Route', ['url', 'mapping', 'name', 'initkwargs'])
+
+
def replace_methodname(format_string, methodname):
"""
Partially format a format_string, swapping out any
@@ -38,8 +42,8 @@ class BaseRouter(object):
def __init__(self):
self.registry = []
- def register(self, prefix, viewset, basename):
- self.registry.append((prefix, viewset, basename))
+ def register(self, prefix, viewset, name):
+ self.registry.append((prefix, viewset, name))
def get_urls(self):
raise NotImplemented('get_urls must be overridden')
@@ -54,33 +58,36 @@ class BaseRouter(object):
class SimpleRouter(BaseRouter):
routes = [
# List route.
- (
- r'^{prefix}/$',
- {
+ Route(
+ url=r'^{prefix}/$',
+ mapping={
'get': 'list',
'post': 'create'
},
- '{basename}-list'
+ name='{basename}-list',
+ initkwargs={'suffix': 'List'}
),
# Detail route.
- (
- r'^{prefix}/{lookup}/$',
- {
+ Route(
+ url=r'^{prefix}/{lookup}/$',
+ mapping={
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
},
- '{basename}-detail'
+ name='{basename}-detail',
+ initkwargs={'suffix': 'Instance'}
),
# Dynamically generated routes.
# Generated using @action or @link decorators on methods of the viewset.
- (
- r'^{prefix}/{lookup}/{methodname}/$',
- {
+ Route(
+ url=r'^{prefix}/{lookup}/{methodname}/$',
+ mapping={
'{httpmethod}': '{methodname}',
},
- '{basename}-{methodnamehyphen}'
+ name='{basename}-{methodnamehyphen}',
+ initkwargs={}
),
]
@@ -88,8 +95,7 @@ class SimpleRouter(BaseRouter):
"""
Augment `self.routes` with any dynamically generated routes.
- Returns a list of 4-tuples, of the form:
- `(url_format, method_map, name_format, extra_kwargs)`
+ Returns a list of the Route namedtuple.
"""
# Determine any `@action` or `@link` decorated methods on the viewset
@@ -101,21 +107,21 @@ class SimpleRouter(BaseRouter):
dynamic_routes[httpmethod] = methodname
ret = []
- for url_format, method_map, name_format in self.routes:
- if method_map == {'{httpmethod}': '{methodname}'}:
+ for route in self.routes:
+ if route.mapping == {'{httpmethod}': '{methodname}'}:
# Dynamic routes (@link or @action decorator)
for httpmethod, methodname in dynamic_routes.items():
- extra_kwargs = getattr(viewset, methodname).kwargs
- ret.append((
- replace_methodname(url_format, methodname),
- {httpmethod: methodname},
- replace_methodname(name_format, methodname),
- extra_kwargs
+ initkwargs = route.initkwargs.copy()
+ initkwargs.update(getattr(viewset, methodname).kwargs)
+ ret.append(Route(
+ url=replace_methodname(route.url, methodname),
+ mapping={httpmethod: methodname},
+ name=replace_methodname(route.name, methodname),
+ initkwargs=initkwargs,
))
else:
# Standard route
- extra_kwargs = {}
- ret.append((url_format, method_map, name_format, extra_kwargs))
+ ret.append(route)
return ret
@@ -150,17 +156,17 @@ class SimpleRouter(BaseRouter):
lookup = self.get_lookup_regex(viewset)
routes = self.get_routes(viewset)
- for url_format, method_map, name_format, extra_kwargs in routes:
+ for route in routes:
# Only actions which actually exist on the viewset will be bound
- method_map = self.get_method_map(viewset, method_map)
- if not method_map:
+ mapping = self.get_method_map(viewset, route.mapping)
+ if not mapping:
continue
# Build the url pattern
- regex = url_format.format(prefix=prefix, lookup=lookup)
- view = viewset.as_view(method_map, **extra_kwargs)
- name = name_format.format(basename=basename)
+ regex = route.url.format(prefix=prefix, lookup=lookup)
+ view = viewset.as_view(mapping, **route.initkwargs)
+ name = route.name.format(basename=basename)
ret.append(url(regex, view, name=name))
return ret
@@ -179,7 +185,7 @@ class DefaultRouter(SimpleRouter):
Return a view to use as the API root.
"""
api_root_dict = {}
- list_name = self.routes[0][-1]
+ list_name = self.routes[0].name
for prefix, viewset, basename in self.registry:
api_root_dict[prefix] = list_name.format(basename=basename)