mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-03 12:00:12 +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:
|
if format is not None:
|
||||||
kwargs = kwargs or {}
|
kwargs = kwargs or {}
|
||||||
kwargs['format'] = format
|
kwargs['format'] = format
|
||||||
|
if request:
|
||||||
|
extra.setdefault('current_app', current_app(request))
|
||||||
url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
|
url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
|
||||||
if request:
|
if request:
|
||||||
return request.build_absolute_uri(url)
|
return request.build_absolute_uri(url)
|
||||||
return 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)
|
reverse_lazy = lazy(reverse, six.text_type)
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
from __future__ import unicode_literals
|
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.test import TestCase, override_settings
|
||||||
from django.urls import NoReverseMatch
|
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
|
from rest_framework.test import APIRequestFactory
|
||||||
|
|
||||||
factory = APIRequestFactory()
|
factory = APIRequestFactory()
|
||||||
|
|
||||||
|
|
||||||
def null_view(request):
|
def mock_view(request):
|
||||||
pass
|
return HttpResponse('')
|
||||||
|
|
||||||
|
|
||||||
|
apppatterns = ([
|
||||||
|
url(r'^home$', mock_view, name='home'),
|
||||||
|
], 'app')
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
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)
|
url = reverse('view', request=request)
|
||||||
assert url == 'http://testserver/view'
|
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