From e6c9f89a123756382cbfa7196ae631e41ef3feaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=99=98?= Date: Thu, 25 May 2017 19:13:45 +0900 Subject: [PATCH 1/3] Fixed curly bracket in regexp of @list_route --- rest_framework/routers.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rest_framework/routers.py b/rest_framework/routers.py index fce968aa0..81f8ebf78 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -35,6 +35,12 @@ DynamicDetailRoute = namedtuple('DynamicDetailRoute', ['url', 'name', 'initkwarg DynamicListRoute = namedtuple('DynamicListRoute', ['url', 'name', 'initkwargs']) +def replace_curly_brackets(url_path): + if ('{' and '}') in url_path: + url_path = url_path.replace('{', '{{').replace('}', '}}') + return url_path + + def replace_methodname(format_string, methodname): """ Partially format a format_string, swapping out any @@ -178,6 +184,7 @@ class SimpleRouter(BaseRouter): initkwargs = route.initkwargs.copy() initkwargs.update(method_kwargs) url_path = initkwargs.pop("url_path", None) or methodname + url_path = replace_curly_brackets(url_path) url_name = initkwargs.pop("url_name", None) or url_path ret.append(Route( url=replace_methodname(route.url, url_path), From 973860d9fe91f59d9c46e086fb5ef1aa839a4bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=99=98?= Date: Sun, 28 May 2017 18:38:09 +0900 Subject: [PATCH 2/3] Added: test for list_route and detail_route with regex url_path --- tests/test_routers.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_routers.py b/tests/test_routers.py index 97f43b91a..fee39b2b3 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -65,6 +65,19 @@ class EmptyPrefixViewSet(viewsets.ModelViewSet): return self.queryset[index] +class RegexUrlPathViewSet(viewsets.ViewSet): + @list_route(url_path='list/(?P[0-9]{4})') + def regex_url_path_list(self, request, *args, **kwargs): + kwarg = self.kwargs.get('kwarg', '') + return Response({'kwarg': kwarg}) + + @detail_route(url_path='detail/(?P[0-9]{4})') + def regex_url_path_detail(self, request, *args, **kwargs): + pk = self.kwargs.get('pk', '') + kwarg = self.kwargs.get('kwarg', '') + return Response({'pk': pk, 'kwarg': kwarg}) + + notes_router = SimpleRouter() notes_router.register(r'notes', NoteViewSet) @@ -80,6 +93,9 @@ empty_prefix_urls = [ url(r'^', include(empty_prefix_router.urls)), ] +regex_url_path_router = SimpleRouter() +regex_url_path_router.register(r'', RegexUrlPathViewSet, base_name='regex') + urlpatterns = [ url(r'^non-namespaced/', include(namespaced_router.urls)), url(r'^namespaced/', include(namespaced_router.urls, namespace='example', app_name='example')), @@ -87,6 +103,7 @@ urlpatterns = [ url(r'^example2/', include(kwarged_notes_router.urls)), url(r'^empty-prefix/', include(empty_prefix_urls)), + url(r'^regex/', include(regex_url_path_router.urls)) ] @@ -402,3 +419,19 @@ class TestEmptyPrefix(TestCase): response = self.client.get('/empty-prefix/1/') assert response.status_code == 200 assert json.loads(response.content.decode('utf-8')) == {'uuid': '111', 'text': 'First'} + + +@override_settings(ROOT_URLCONF='tests.test_routers') +class TestRegexUrlPath(TestCase): + def test_regex_url_path_list(self): + kwarg = '1234' + response = self.client.get('/regex/list/{}/'.format(kwarg)) + assert response.status_code == 200 + assert json.loads(response.content.decode('utf-8')) == {'kwarg': kwarg} + + def test_regex_url_path_detail(self): + pk = '1' + kwarg = '1234' + response = self.client.get('/regex/{}/detail/{}/'.format(pk, kwarg)) + assert response.status_code == 200 + assert json.loads(response.content.decode('utf-8')) == {'pk': pk, 'kwarg': kwarg} From 0ad017a5735a532280c8c56ad8c66f950f0b22f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=99=98?= Date: Mon, 29 May 2017 20:55:06 +0900 Subject: [PATCH 3/3] requested changes --- rest_framework/routers.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 81f8ebf78..87e58b015 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -35,7 +35,10 @@ DynamicDetailRoute = namedtuple('DynamicDetailRoute', ['url', 'name', 'initkwarg DynamicListRoute = namedtuple('DynamicListRoute', ['url', 'name', 'initkwargs']) -def replace_curly_brackets(url_path): +def escape_curly_brackets(url_path): + """ + Double brackets in regex of url_path for escape string formatting + """ if ('{' and '}') in url_path: url_path = url_path.replace('{', '{{').replace('}', '}}') return url_path @@ -184,7 +187,7 @@ class SimpleRouter(BaseRouter): initkwargs = route.initkwargs.copy() initkwargs.update(method_kwargs) url_path = initkwargs.pop("url_path", None) or methodname - url_path = replace_curly_brackets(url_path) + url_path = escape_curly_brackets(url_path) url_name = initkwargs.pop("url_name", None) or url_path ret.append(Route( url=replace_methodname(route.url, url_path),