mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-03 19:00:17 +03:00
Support namespaced router URLs with DefaultRouter.
This commit is contained in:
parent
67fc002f91
commit
efa5942ce1
|
@ -50,6 +50,16 @@ except ImportError:
|
||||||
from django.http import HttpResponse as HttpResponseBase
|
from django.http import HttpResponse as HttpResponseBase
|
||||||
|
|
||||||
|
|
||||||
|
# request only provides `resolver_match` from 1.5 onwards.
|
||||||
|
def get_resolver_match(request):
|
||||||
|
try:
|
||||||
|
return request.resolver_match
|
||||||
|
except AttributeError:
|
||||||
|
# Django < 1.5
|
||||||
|
from django.core.urlresolvers import resolve
|
||||||
|
return resolve(request.path_info)
|
||||||
|
|
||||||
|
|
||||||
# django-filter is optional
|
# django-filter is optional
|
||||||
try:
|
try:
|
||||||
import django_filters
|
import django_filters
|
||||||
|
|
|
@ -21,7 +21,7 @@ from django.conf.urls import patterns, url
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.urlresolvers import NoReverseMatch
|
from django.core.urlresolvers import NoReverseMatch
|
||||||
from rest_framework import views
|
from rest_framework import views
|
||||||
from rest_framework.compat import OrderedDict
|
from rest_framework.compat import get_resolver_match, OrderedDict
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
from rest_framework.urlpatterns import format_suffix_patterns
|
from rest_framework.urlpatterns import format_suffix_patterns
|
||||||
|
@ -292,7 +292,10 @@ class DefaultRouter(SimpleRouter):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
ret = OrderedDict()
|
ret = OrderedDict()
|
||||||
|
namespace = get_resolver_match(request).namespace
|
||||||
for key, url_name in api_root_dict.items():
|
for key, url_name in api_root_dict.items():
|
||||||
|
if namespace:
|
||||||
|
url_name = namespace + ':' + url_name
|
||||||
try:
|
try:
|
||||||
ret[key] = reverse(
|
ret[key] = reverse(
|
||||||
url_name,
|
url_name,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.conf.urls import patterns, url, include
|
from django.conf.urls import url, include
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
@ -12,7 +12,42 @@ from collections import namedtuple
|
||||||
|
|
||||||
factory = APIRequestFactory()
|
factory = APIRequestFactory()
|
||||||
|
|
||||||
urlpatterns = patterns('',)
|
|
||||||
|
class RouterTestModel(models.Model):
|
||||||
|
uuid = models.CharField(max_length=20)
|
||||||
|
text = models.CharField(max_length=200)
|
||||||
|
|
||||||
|
|
||||||
|
class NoteSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
url = serializers.HyperlinkedIdentityField(view_name='routertestmodel-detail', lookup_field='uuid')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = RouterTestModel
|
||||||
|
fields = ('url', 'uuid', 'text')
|
||||||
|
|
||||||
|
|
||||||
|
class NoteViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = RouterTestModel.objects.all()
|
||||||
|
serializer_class = NoteSerializer
|
||||||
|
lookup_field = 'uuid'
|
||||||
|
|
||||||
|
|
||||||
|
class MockViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = None
|
||||||
|
serializer_class = None
|
||||||
|
|
||||||
|
|
||||||
|
notes_router = SimpleRouter()
|
||||||
|
notes_router.register(r'notes', NoteViewSet)
|
||||||
|
|
||||||
|
namespaced_router = DefaultRouter()
|
||||||
|
namespaced_router.register(r'example', MockViewSet, base_name='example')
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^non-namespaced/', include(namespaced_router.urls)),
|
||||||
|
url(r'^namespaced/', include(namespaced_router.urls, namespace='example')),
|
||||||
|
url(r'^example/', include(notes_router.urls)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class BasicViewSet(viewsets.ViewSet):
|
class BasicViewSet(viewsets.ViewSet):
|
||||||
|
@ -64,9 +99,26 @@ class TestSimpleRouter(TestCase):
|
||||||
self.assertEqual(route.mapping[method], endpoint)
|
self.assertEqual(route.mapping[method], endpoint)
|
||||||
|
|
||||||
|
|
||||||
class RouterTestModel(models.Model):
|
class TestRootView(TestCase):
|
||||||
uuid = models.CharField(max_length=20)
|
urls = 'tests.test_routers'
|
||||||
text = models.CharField(max_length=200)
|
|
||||||
|
def test_retrieve_namespaced_root(self):
|
||||||
|
response = self.client.get('/namespaced/')
|
||||||
|
self.assertEqual(
|
||||||
|
response.data,
|
||||||
|
{
|
||||||
|
"example": "http://testserver/namespaced/example/",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_retrieve_non_namespaced_root(self):
|
||||||
|
response = self.client.get('/non-namespaced/')
|
||||||
|
self.assertEqual(
|
||||||
|
response.data,
|
||||||
|
{
|
||||||
|
"example": "http://testserver/non-namespaced/example/",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCustomLookupFields(TestCase):
|
class TestCustomLookupFields(TestCase):
|
||||||
|
@ -76,51 +128,29 @@ class TestCustomLookupFields(TestCase):
|
||||||
urls = 'tests.test_routers'
|
urls = 'tests.test_routers'
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class NoteSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
url = serializers.HyperlinkedIdentityField(view_name='routertestmodel-detail', lookup_field='uuid')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = RouterTestModel
|
|
||||||
fields = ('url', 'uuid', 'text')
|
|
||||||
|
|
||||||
class NoteViewSet(viewsets.ModelViewSet):
|
|
||||||
queryset = RouterTestModel.objects.all()
|
|
||||||
serializer_class = NoteSerializer
|
|
||||||
lookup_field = 'uuid'
|
|
||||||
|
|
||||||
self.router = SimpleRouter()
|
|
||||||
self.router.register(r'notes', NoteViewSet)
|
|
||||||
|
|
||||||
from tests import test_routers
|
|
||||||
urls = getattr(test_routers, 'urlpatterns')
|
|
||||||
urls += patterns(
|
|
||||||
'',
|
|
||||||
url(r'^', include(self.router.urls)),
|
|
||||||
)
|
|
||||||
|
|
||||||
RouterTestModel.objects.create(uuid='123', text='foo bar')
|
RouterTestModel.objects.create(uuid='123', text='foo bar')
|
||||||
|
|
||||||
def test_custom_lookup_field_route(self):
|
def test_custom_lookup_field_route(self):
|
||||||
detail_route = self.router.urls[-1]
|
detail_route = notes_router.urls[-1]
|
||||||
detail_url_pattern = detail_route.regex.pattern
|
detail_url_pattern = detail_route.regex.pattern
|
||||||
self.assertIn('<uuid>', detail_url_pattern)
|
self.assertIn('<uuid>', detail_url_pattern)
|
||||||
|
|
||||||
def test_retrieve_lookup_field_list_view(self):
|
def test_retrieve_lookup_field_list_view(self):
|
||||||
response = self.client.get('/notes/')
|
response = self.client.get('/example/notes/')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.data,
|
response.data,
|
||||||
[{
|
[{
|
||||||
"url": "http://testserver/notes/123/",
|
"url": "http://testserver/example/notes/123/",
|
||||||
"uuid": "123", "text": "foo bar"
|
"uuid": "123", "text": "foo bar"
|
||||||
}]
|
}]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_retrieve_lookup_field_detail_view(self):
|
def test_retrieve_lookup_field_detail_view(self):
|
||||||
response = self.client.get('/notes/123/')
|
response = self.client.get('/example/notes/123/')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.data,
|
response.data,
|
||||||
{
|
{
|
||||||
"url": "http://testserver/notes/123/",
|
"url": "http://testserver/example/notes/123/",
|
||||||
"uuid": "123", "text": "foo bar"
|
"uuid": "123", "text": "foo bar"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user