Skip to content

Commit

Permalink
Merge pull request #2685 from rbarrois/rbarrois/fix_lookup_url_kwarg
Browse files Browse the repository at this point in the history
Fix lookup_url_kwarg handling in viewsets (Fixes #2591).
  • Loading branch information
xordoquy committed Mar 13, 2015
2 parents a02098b + 8d0dbc8 commit cc64e30
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
5 changes: 3 additions & 2 deletions rest_framework/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,15 @@ def get_lookup_regex(self, viewset, lookup_prefix=''):
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
)

Expand Down
38 changes: 38 additions & 0 deletions tests/test_routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,13 +47,17 @@ 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')

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)),
]


Expand Down Expand Up @@ -177,6 +188,33 @@ def test_urls_limited_by_lookup_value_regex(self):
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):
Expand Down

0 comments on commit cc64e30

Please sign in to comment.