mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-05-14 21:03:43 +03:00
Merge pull request #1333 from bodylabs/2.4.0+lookup_regex
Let viewsets specify their regex
This commit is contained in:
commit
4ab97843e8
|
@ -83,6 +83,12 @@ This behavior can be modified by setting the `trailing_slash` argument to `False
|
||||||
|
|
||||||
Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.
|
Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.
|
||||||
|
|
||||||
|
The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset. For example, you can limit the lookup to valid UUIDs:
|
||||||
|
|
||||||
|
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||||
|
lookup_field = 'my_model_id'
|
||||||
|
lookup_value_regex = '[0-9a-f]{32}'
|
||||||
|
|
||||||
## DefaultRouter
|
## DefaultRouter
|
||||||
|
|
||||||
This router is similar to `SimpleRouter` as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional `.json` style format suffixes.
|
This router is similar to `SimpleRouter` as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional `.json` style format suffixes.
|
||||||
|
|
|
@ -219,13 +219,18 @@ class SimpleRouter(BaseRouter):
|
||||||
|
|
||||||
https://github.com/alanjds/drf-nested-routers
|
https://github.com/alanjds/drf-nested-routers
|
||||||
"""
|
"""
|
||||||
if self.trailing_slash:
|
base_regex = '(?P<{lookup_prefix}{lookup_field}>{lookup_value})'
|
||||||
base_regex = '(?P<{lookup_prefix}{lookup_field}>[^/]+)'
|
|
||||||
else:
|
|
||||||
# Don't consume `.json` style suffixes
|
|
||||||
base_regex = '(?P<{lookup_prefix}{lookup_field}>[^/.]+)'
|
|
||||||
lookup_field = getattr(viewset, 'lookup_field', 'pk')
|
lookup_field = getattr(viewset, 'lookup_field', 'pk')
|
||||||
return base_regex.format(lookup_field=lookup_field, lookup_prefix=lookup_prefix)
|
try:
|
||||||
|
lookup_value = viewset.lookup_value_regex
|
||||||
|
except AttributeError:
|
||||||
|
# Don't consume `.json` style suffixes
|
||||||
|
lookup_value = '[^/.]+'
|
||||||
|
return base_regex.format(
|
||||||
|
lookup_prefix=lookup_prefix,
|
||||||
|
lookup_field=lookup_field,
|
||||||
|
lookup_value=lookup_value
|
||||||
|
)
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -121,6 +121,27 @@ class TestCustomLookupFields(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestLookupValueRegex(TestCase):
|
||||||
|
"""
|
||||||
|
Ensure the router honors lookup_value_regex when applied
|
||||||
|
to the viewset.
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
class NoteViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = RouterTestModel.objects.all()
|
||||||
|
lookup_field = 'uuid'
|
||||||
|
lookup_value_regex = '[0-9a-f]{32}'
|
||||||
|
|
||||||
|
self.router = SimpleRouter()
|
||||||
|
self.router.register(r'notes', NoteViewSet)
|
||||||
|
self.urls = self.router.urls
|
||||||
|
|
||||||
|
def test_urls_limited_by_lookup_value_regex(self):
|
||||||
|
expected = ['^notes/$', '^notes/(?P<uuid>[0-9a-f]{32})/$']
|
||||||
|
for idx in range(len(expected)):
|
||||||
|
self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
|
||||||
|
|
||||||
|
|
||||||
class TestTrailingSlashIncluded(TestCase):
|
class TestTrailingSlashIncluded(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class NoteViewSet(viewsets.ModelViewSet):
|
class NoteViewSet(viewsets.ModelViewSet):
|
||||||
|
@ -131,7 +152,7 @@ class TestTrailingSlashIncluded(TestCase):
|
||||||
self.urls = self.router.urls
|
self.urls = self.router.urls
|
||||||
|
|
||||||
def test_urls_have_trailing_slash_by_default(self):
|
def test_urls_have_trailing_slash_by_default(self):
|
||||||
expected = ['^notes/$', '^notes/(?P<pk>[^/]+)/$']
|
expected = ['^notes/$', '^notes/(?P<pk>[^/.]+)/$']
|
||||||
for idx in range(len(expected)):
|
for idx in range(len(expected)):
|
||||||
self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
|
self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user