Add support for namespaces to DefaultRouter.

This commit is contained in:
Rocky Meza 2014-12-21 03:46:54 -07:00
parent e4c7c10b00
commit 4ba48d3460
4 changed files with 61 additions and 0 deletions

View File

@ -140,6 +140,17 @@ As with `SimpleRouter` the trailing slashes on the URL routes can be removed by
router = DefaultRouter(trailing_slash=False)
If you wish to put the router namespace, you will need to pass the `namespace` name to `DefaultRouter`.
router = DefaultRouter(namespace='api')
urlpatterns = [
url(r'^', include(router.urls, namespace='api')),
]
Please note if you do this, you will have to specify your namespace in your serializers too.
url = serializers.HyperlinkedIdentityField(view_name='api:mymodel-detail')
# Custom Routers
Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are structured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.

View File

@ -278,6 +278,10 @@ class DefaultRouter(SimpleRouter):
include_format_suffixes = True
root_view_name = 'api-root'
def __init__(self, *args, **kwargs):
self.namespace = kwargs.pop('namespace', None)
super(DefaultRouter, self).__init__(*args, **kwargs)
def get_api_root_view(self):
"""
Return a view to use as the API root.
@ -287,12 +291,16 @@ class DefaultRouter(SimpleRouter):
for prefix, viewset, basename in self.registry:
api_root_dict[prefix] = list_name.format(basename=basename)
namespace = self.namespace
class APIRoot(views.APIView):
_ignore_model_permissions = True
def get(self, request, *args, **kwargs):
ret = OrderedDict()
for key, url_name in api_root_dict.items():
if namespace:
url_name = '%s:%s' % (namespace, url_name)
try:
ret[key] = reverse(
url_name,

32
tests/namespaced_urls.py Normal file
View File

@ -0,0 +1,32 @@
from django.conf.urls import url, include
from django.db import models
from rest_framework import serializers, viewsets, routers
class NamespacedRouterTestModel(models.Model):
uuid = models.CharField(max_length=20)
text = models.CharField(max_length=200)
class NoteSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='api-namespace:routertestmodel-detail', lookup_field='uuid')
class Meta:
model = NamespacedRouterTestModel
fields = ('url', 'uuid', 'text')
class NoteViewSet(viewsets.ModelViewSet):
queryset = NamespacedRouterTestModel.objects.all()
serializer_class = NoteSerializer
lookup_field = 'uuid'
router = routers.DefaultRouter(namespace='api-namespace')
router.register(r'note', NoteViewSet)
urlpatterns = [
url('^namespaced-api/', include(router.urls, namespace='api-namespace')),
]

View File

@ -321,3 +321,13 @@ class TestRootWithAListlessViewset(TestCase):
request = factory.get('/')
response = self.view(request)
self.assertEqual(response.data, {})
class TestNamespacedDefaultRouter(TestCase):
urls = 'tests.namespaced_urls'
def test_api_root(self):
from django.core.urlresolvers import reverse
url = reverse('api-namespace:api-root')
response = self.client.get(url)
self.assertEqual(response.data['note'], 'http://testserver/namespaced-api/note/')