mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-02 19:40:13 +03:00
Add request.current_app handling to drf reverse
This commit is contained in:
parent
1664588500
commit
4fbe3ecce6
|
@ -60,10 +60,27 @@ def _reverse(viewname, args=None, kwargs=None, request=None, format=None, **extr
|
|||
if format is not None:
|
||||
kwargs = kwargs or {}
|
||||
kwargs['format'] = format
|
||||
if request:
|
||||
extra.setdefault('current_app', current_app(request))
|
||||
url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
|
||||
if request:
|
||||
return request.build_absolute_uri(url)
|
||||
return url
|
||||
|
||||
|
||||
def current_app(request):
|
||||
"""
|
||||
Get the current app for the request.
|
||||
|
||||
This code is copied from the URL tag.
|
||||
"""
|
||||
try:
|
||||
return request.current_app
|
||||
except AttributeError:
|
||||
try:
|
||||
return request.resolver_match.namespace
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
|
||||
reverse_lazy = lazy(reverse, six.text_type)
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import include, url
|
||||
from django.http import HttpResponse
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import NoReverseMatch
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
from rest_framework.reverse import current_app, reverse
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
factory = APIRequestFactory()
|
||||
|
||||
|
||||
def null_view(request):
|
||||
pass
|
||||
def mock_view(request):
|
||||
return HttpResponse('')
|
||||
|
||||
|
||||
apppatterns = ([
|
||||
url(r'^home$', mock_view, name='home'),
|
||||
], 'app')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^view$', null_view, name='view'),
|
||||
url(r'^view$', mock_view, name='view'),
|
||||
url(r'^app2/', include(apppatterns, namespace='app2')),
|
||||
url(r'^app1/', include(apppatterns, namespace='app1')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -54,3 +62,85 @@ class ReverseTests(TestCase):
|
|||
|
||||
url = reverse('view', request=request)
|
||||
assert url == 'http://testserver/view'
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='tests.test_reverse')
|
||||
class NamespaceTests(TestCase):
|
||||
"""
|
||||
Ensure reverse can handle namespaces.
|
||||
|
||||
Note: It's necessary to use self.client() here, as the
|
||||
RequestFactory does not setup the resolver_match.
|
||||
"""
|
||||
|
||||
def request(self, url):
|
||||
return self.client.get(url).wsgi_request
|
||||
|
||||
def test_application_namespace(self):
|
||||
url = reverse('app:home')
|
||||
assert url == '/app1/home'
|
||||
|
||||
# instance namespace provided by current_app
|
||||
url = reverse('app:home', current_app='app2')
|
||||
assert url == '/app2/home'
|
||||
|
||||
def test_instance_namespace(self):
|
||||
url = reverse('app1:home')
|
||||
assert url == '/app1/home'
|
||||
|
||||
url = reverse('app2:home')
|
||||
assert url == '/app2/home'
|
||||
|
||||
def test_application_namespace_with_request(self):
|
||||
# request's current app affects result
|
||||
request1 = self.request('/app1/home')
|
||||
request2 = self.request('/app2/home')
|
||||
|
||||
# sanity check
|
||||
assert current_app(request1) == 'app1'
|
||||
assert current_app(request2) == 'app2'
|
||||
|
||||
assert reverse('app:home', request=request1) == 'http://testserver/app1/home'
|
||||
assert reverse('app:home', request=request2) == 'http://testserver/app2/home'
|
||||
|
||||
def test_instance_namespace_with_request(self):
|
||||
# request's current app is not relevant
|
||||
request1 = self.request('/app1/home')
|
||||
request2 = self.request('/app2/home')
|
||||
|
||||
# sanity check
|
||||
assert current_app(request1) == 'app1'
|
||||
assert current_app(request2) == 'app2'
|
||||
|
||||
assert reverse('app1:home', request=request1) == 'http://testserver/app1/home'
|
||||
assert reverse('app2:home', request=request1) == 'http://testserver/app2/home'
|
||||
assert reverse('app1:home', request=request2) == 'http://testserver/app1/home'
|
||||
assert reverse('app2:home', request=request2) == 'http://testserver/app2/home'
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='tests.test_reverse')
|
||||
class CurrentAppTests(TestCase):
|
||||
"""
|
||||
Test current_app() function.
|
||||
|
||||
Note: It's necessary to use self.client() here, as the
|
||||
RequestFactory does not setup the resolver_match.
|
||||
"""
|
||||
|
||||
def request(self, url):
|
||||
return self.client.get(url).wsgi_request
|
||||
|
||||
def test_no_namespace(self):
|
||||
request = self.request('/view')
|
||||
assert current_app(request) == ''
|
||||
|
||||
def test_namespace(self):
|
||||
request = self.request('/app1/home')
|
||||
assert current_app(request) == 'app1'
|
||||
|
||||
request = self.request('/app2/home')
|
||||
assert current_app(request) == 'app2'
|
||||
|
||||
def test_factory_incompatibility(self):
|
||||
request = factory.get('/app1/home')
|
||||
assert current_app(request) is None
|
||||
|
|
Loading…
Reference in New Issue
Block a user