mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespaces (#7278)
* Fix the case where if the namespace is not None and there's no match, NamespaceVersioning always raises NotFound even if DEFAULT_VERSION is set or None is in ALLOWED_VERSIONS * Add test cases
This commit is contained in:
		
							parent
							
								
									aed7761a8d
								
							
						
					
					
						commit
						71f87a5864
					
				| 
						 | 
				
			
			@ -119,15 +119,16 @@ class NamespaceVersioning(BaseVersioning):
 | 
			
		|||
 | 
			
		||||
    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
 | 
			
		||||
        if resolver_match is not None and resolver_match.namespace:
 | 
			
		||||
            # Allow for possibly nested namespaces.
 | 
			
		||||
            possible_versions = resolver_match.namespace.split(':')
 | 
			
		||||
            for version in possible_versions:
 | 
			
		||||
                if self.is_allowed_version(version):
 | 
			
		||||
                    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)
 | 
			
		||||
        if not self.is_allowed_version(self.default_version):
 | 
			
		||||
            raise exceptions.NotFound(self.invalid_version_message)
 | 
			
		||||
        return self.default_version
 | 
			
		||||
 | 
			
		||||
    def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
 | 
			
		||||
        if request.version is not None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -272,7 +272,7 @@ class TestInvalidVersion:
 | 
			
		|||
        assert response.status_code == status.HTTP_404_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestAllowedAndDefaultVersion:
 | 
			
		||||
class TestAcceptHeaderAllowedAndDefaultVersion:
 | 
			
		||||
    def test_missing_without_default(self):
 | 
			
		||||
        scheme = versioning.AcceptHeaderVersioning
 | 
			
		||||
        view = AllowedVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
| 
						 | 
				
			
			@ -318,6 +318,97 @@ class TestAllowedAndDefaultVersion:
 | 
			
		|||
        assert response.data == {'version': 'v2'}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestNamespaceAllowedAndDefaultVersion:
 | 
			
		||||
    def test_no_namespace_without_default(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = None
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_404_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
    def test_no_namespace_with_default(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = None
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedAndDefaultVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == {'version': 'v2'}
 | 
			
		||||
 | 
			
		||||
    def test_no_match_without_default(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = 'no_match'
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_404_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
    def test_no_match_with_default(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = 'no_match'
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedAndDefaultVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == {'version': 'v2'}
 | 
			
		||||
 | 
			
		||||
    def test_with_default(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = 'v1'
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedAndDefaultVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == {'version': 'v1'}
 | 
			
		||||
 | 
			
		||||
    def test_no_match_without_default_but_none_allowed(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = 'no_match'
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedWithNoneVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == {'version': None}
 | 
			
		||||
 | 
			
		||||
    def test_no_match_with_default_and_none_allowed(self):
 | 
			
		||||
        class FakeResolverMatch:
 | 
			
		||||
            namespace = 'no_match'
 | 
			
		||||
 | 
			
		||||
        scheme = versioning.NamespaceVersioning
 | 
			
		||||
        view = AllowedWithNoneAndDefaultVersionsView.as_view(versioning_class=scheme)
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/endpoint/')
 | 
			
		||||
        request.resolver_match = FakeResolverMatch
 | 
			
		||||
        response = view(request)
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == {'version': 'v2'}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestHyperlinkedRelatedField(URLPatternsTestCase, APITestCase):
 | 
			
		||||
    included = [
 | 
			
		||||
        path('namespaced/<int:pk>/', dummy_pk_view, name='namespaced'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user