15
15
"""
16
16
from __future__ import unicode_literals
17
17
18
+ import itertools
18
19
from collections import namedtuple
20
+ from django .core .exceptions import ImproperlyConfigured
19
21
from rest_framework import views
20
22
from rest_framework .compat import patterns , url
21
23
from rest_framework .response import Response
@@ -38,6 +40,13 @@ def replace_methodname(format_string, methodname):
38
40
return ret
39
41
40
42
43
+ def flatten (list_of_lists ):
44
+ """
45
+ Takes an iterable of iterables, returns a single iterable containing all items
46
+ """
47
+ return itertools .chain (* list_of_lists )
48
+
49
+
41
50
class BaseRouter (object ):
42
51
def __init__ (self ):
43
52
self .registry = []
@@ -130,12 +139,17 @@ def get_routes(self, viewset):
130
139
Returns a list of the Route namedtuple.
131
140
"""
132
141
142
+ known_actions = flatten ([route .mapping .values () for route in self .routes ])
143
+
133
144
# Determine any `@action` or `@link` decorated methods on the viewset
134
145
dynamic_routes = []
135
146
for methodname in dir (viewset ):
136
147
attr = getattr (viewset , methodname )
137
148
httpmethods = getattr (attr , 'bind_to_methods' , None )
138
149
if httpmethods :
150
+ if methodname in known_actions :
151
+ raise ImproperlyConfigured ('Cannot use @action or @link decorator on '
152
+ 'method "%s" as it is an existing route' % methodname )
139
153
httpmethods = [method .lower () for method in httpmethods ]
140
154
dynamic_routes .append ((httpmethods , methodname ))
141
155
0 commit comments