Transparently keep reference of routers in urls generated by routers

This commit is contained in:
Dimitri Justeau 2016-08-26 17:00:22 +11:00
parent b683cd7afc
commit 14a6b7b09f
2 changed files with 47 additions and 3 deletions

View File

@ -0,0 +1,44 @@
# coding: utf-8
import django
if django.VERSION >= (1, 10):
from django.urls.resolvers import RegexURLPattern, RegexURLResolver
else:
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
class DrfRegexURLPattern(RegexURLPattern):
"""
Drf specific RegexURLPattern that can be instantiated with a router,
for reflexion purposes.
"""
def __init__(self, *args, **kwargs):
self.router = kwargs.pop("router", None)
super(DrfRegexURLPattern, self).__init__(*args, **kwargs)
class DrfRegexURLResolver(RegexURLResolver):
"""
Drf specific RegexURLResolver that can be instantiated with a router,
for reflexion purposes.
"""
def __init__(self, *args, **kwargs):
self.router = kwargs.pop("router", None)
super(DrfRegexURLResolver, self).__init__(*args, **kwargs)
def url(regex, view, kwargs=None, name=None, router=None):
"""
Rewrite of the django's django.conf.urls.url function, taking an extra
'router' parameter and returning DrfRegexURLPattern or DrfRegexURLResolver
instance instead of RegexURLPattern or RegexURLResolver.
"""
if isinstance(view, (list, tuple)):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return DrfRegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace, router=router)
elif callable(view):
return DrfRegexURLPattern(regex, view, kwargs, name, router=router)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')

View File

@ -18,11 +18,11 @@ from __future__ import unicode_literals
import itertools import itertools
from collections import OrderedDict, namedtuple from collections import OrderedDict, namedtuple
from django.conf.urls import 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 exceptions, renderers, views from rest_framework import exceptions, renderers, views
from rest_framework.resolvers import url
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.schemas import SchemaGenerator from rest_framework.schemas import SchemaGenerator
@ -260,7 +260,7 @@ class SimpleRouter(BaseRouter):
view = viewset.as_view(mapping, **route.initkwargs) view = viewset.as_view(mapping, **route.initkwargs)
name = route.name.format(basename=basename) name = route.name.format(basename=basename)
ret.append(url(regex, view, name=name)) ret.append(url(regex, view, name=name, router=self))
return ret return ret
@ -356,7 +356,7 @@ class DefaultRouter(SimpleRouter):
if self.include_root_view: if self.include_root_view:
view = self.get_api_root_view(api_urls=urls) view = self.get_api_root_view(api_urls=urls)
root_url = url(r'^$', view, name=self.root_view_name) root_url = url(r'^$', view, name=self.root_view_name, router=self)
urls.append(root_url) urls.append(root_url)
if self.include_format_suffixes: if self.include_format_suffixes: