diff --git a/rest_framework/versioning.py b/rest_framework/versioning.py index e27c7b316..763a92b4c 100644 --- a/rest_framework/versioning.py +++ b/rest_framework/versioning.py @@ -112,16 +112,19 @@ class NamespaceVersioning(BaseVersioning): Host: example.com Accept: application/json """ - invalid_version_message = _('Invalid version in URL path.') + invalid_version_message = _('Invalid version in URL path. Does not match any version namespace.') def determine_version(self, request, *args, **kwargs): resolver_match = getattr(request, 'resolver_match', None) if (resolver_match is None or not resolver_match.namespace): return self.default_version - version = resolver_match.namespace - if not self.is_allowed_version(version): - raise exceptions.NotFound(self.invalid_version_message) - return version + + # Allow for possibly nested namespaces. + possible_versions = resolver_match.namespace.split(':') + for version in possible_versions: + if self.is_allowed_version(version): + return version + raise exceptions.NotFound(self.invalid_version_message) def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra): if request.version is not None: diff --git a/tests/test_versioning.py b/tests/test_versioning.py index 5b77e8263..f53eddcbd 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -296,8 +296,12 @@ class TestHyperlinkedRelatedField(URLPatternsTestCase): class TestNamespaceVersioningHyperlinkedRelatedFieldScheme(URLPatternsTestCase): + nested = [ + url(r'^namespaced/(?P\d+)/$', dummy_pk_view, name='nested'), + ] included = [ url(r'^namespaced/(?P\d+)/$', dummy_pk_view, name='namespaced'), + url(r'^nested/', include(nested, namespace='nested-namespace')) ] urlpatterns = [ @@ -325,6 +329,10 @@ class TestNamespaceVersioningHyperlinkedRelatedFieldScheme(URLPatternsTestCase): field = self._create_field('namespaced', 'v2') assert field.to_representation(PKOnlyObject(5)) == 'http://testserver/v2/namespaced/5/' + def test_api_url_is_properly_reversed_with_nested(self): + field = self._create_field('nested', 'v1:nested-namespace') + assert field.to_representation(PKOnlyObject(3)) == 'http://testserver/v1/nested/namespaced/3/' + def test_non_api_url_is_properly_reversed_regardless_of_the_version(self): """ Regression test for #2711