diff options
| -rw-r--r-- | rest_framework/routers.py | 5 | ||||
| -rw-r--r-- | tests/test_routers.py | 38 | 
2 files changed, 41 insertions, 2 deletions
| diff --git a/rest_framework/routers.py b/rest_framework/routers.py index b1e39ff7..4df852bf 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -218,14 +218,15 @@ class SimpleRouter(BaseRouter):          https://github.com/alanjds/drf-nested-routers          """ -        base_regex = '(?P<{lookup_prefix}{lookup_field}>{lookup_value})' +        base_regex = '(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})'          # Use `pk` as default field, unset set.  Default regex should not          # consume `.json` style suffixes and should break at '/' boundaries.          lookup_field = getattr(viewset, 'lookup_field', 'pk') +        lookup_url_kwarg = getattr(viewset, 'lookup_url_kwarg', None) or lookup_field          lookup_value = getattr(viewset, 'lookup_value_regex', '[^/.]+')          return base_regex.format(              lookup_prefix=lookup_prefix, -            lookup_field=lookup_field, +            lookup_url_kwarg=lookup_url_kwarg,              lookup_value=lookup_value          ) diff --git a/tests/test_routers.py b/tests/test_routers.py index 08c58ec7..19eeb868 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -32,6 +32,13 @@ class NoteViewSet(viewsets.ModelViewSet):      lookup_field = 'uuid' +class KWargedNoteViewSet(viewsets.ModelViewSet): +    queryset = RouterTestModel.objects.all() +    serializer_class = NoteSerializer +    lookup_field = 'text__contains' +    lookup_url_kwarg = 'text' + +  class MockViewSet(viewsets.ModelViewSet):      queryset = None      serializer_class = None @@ -40,6 +47,9 @@ class MockViewSet(viewsets.ModelViewSet):  notes_router = SimpleRouter()  notes_router.register(r'notes', NoteViewSet) +kwarged_notes_router = SimpleRouter() +kwarged_notes_router.register(r'notes', KWargedNoteViewSet) +  namespaced_router = DefaultRouter()  namespaced_router.register(r'example', MockViewSet, base_name='example') @@ -47,6 +57,7 @@ urlpatterns = [      url(r'^non-namespaced/', include(namespaced_router.urls)),      url(r'^namespaced/', include(namespaced_router.urls, namespace='example')),      url(r'^example/', include(notes_router.urls)), +    url(r'^example2/', include(kwarged_notes_router.urls)),  ] @@ -177,6 +188,33 @@ class TestLookupValueRegex(TestCase):              self.assertEqual(expected[idx], self.urls[idx].regex.pattern) +class TestLookupUrlKwargs(TestCase): +    """ +    Ensure the router honors lookup_url_kwarg. + +    Setup a deep lookup_field, but map it to a simple URL kwarg. +    """ +    urls = 'tests.test_routers' + +    def setUp(self): +        RouterTestModel.objects.create(uuid='123', text='foo bar') + +    def test_custom_lookup_url_kwarg_route(self): +        detail_route = kwarged_notes_router.urls[-1] +        detail_url_pattern = detail_route.regex.pattern +        self.assertIn('^notes/(?P<text>', detail_url_pattern) + +    def test_retrieve_lookup_url_kwarg_detail_view(self): +        response = self.client.get('/example2/notes/fo/') +        self.assertEqual( +            response.data, +            { +                "url": "http://testserver/example/notes/123/", +                "uuid": "123", "text": "foo bar" +            } +        ) + +  class TestTrailingSlashIncluded(TestCase):      def setUp(self):          class NoteViewSet(viewsets.ModelViewSet): | 
