From a6aebb66b9fe2007feb90e4a9573149e59b055b0 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 14 Jul 2016 18:03:47 -0500 Subject: [PATCH] Multiples @detail_route with the same `url_path` This commit allows you to have multiple class method in your ViewSet each one with the same 'url_path' but different HTTP method, e.g.: class MyViewSet(viewsets.GenericViewset): @detail_route(methods=['get'], url_path='cancel') def cancel_get(self, *args, **kwargs): pass @detail_route(methods=['post'], url_path='cancel') def cancel_post(self, *args, **kwargs): pass --- rest_framework/routers.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 69d73e842..1c9ed50b6 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -238,7 +238,7 @@ class SimpleRouter(BaseRouter): """ Use the registered viewsets to generate a list of URL patterns. """ - ret = [] + urls_data = {} for prefix, viewset, basename in self.registry: lookup = self.get_lookup_regex(viewset) @@ -260,7 +260,31 @@ class SimpleRouter(BaseRouter): view = viewset.as_view(mapping, **route.initkwargs) name = route.name.format(basename=basename) - ret.append(url(regex, view, name=name)) + + # It is possible to define multiples '@detail_route' for the + # same endpoint with different methods (GET, POST, etc). So, we + # need to merge all those routes with the same URL allowing + # those multiples method + if regex in urls_data: + # merge mapping and view for the same regex + urls_data[regex]['mapping'].update(mapping) + else: + urls_data[regex] = { + 'mapping': mapping, + 'viewset': viewset, + 'route': route, + 'name': name, + } + + ret = [] + # Build all the URLs for the values saved on the previous iteration + for regex, values in urls_data.items(): + name = values['name'] + view = values['viewset'].as_view( + values['mapping'], + **values['route'].initkwargs + ) + ret.append(url(regex, view, name=name)) return ret