From 14a6b7b09fb6c6fc643153981016b59c9d399a89 Mon Sep 17 00:00:00 2001 From: Dimitri Justeau Date: Fri, 26 Aug 2016 17:00:22 +1100 Subject: [PATCH] Transparently keep reference of routers in urls generated by routers --- rest_framework/resolvers.py | 44 +++++++++++++++++++++++++++++++++++++ rest_framework/routers.py | 6 ++--- 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 rest_framework/resolvers.py diff --git a/rest_framework/resolvers.py b/rest_framework/resolvers.py new file mode 100644 index 000000000..e3b991c4e --- /dev/null +++ b/rest_framework/resolvers.py @@ -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().') diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 4eec70bda..90994bc78 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -18,11 +18,11 @@ from __future__ import unicode_literals import itertools from collections import OrderedDict, namedtuple -from django.conf.urls import url from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import NoReverseMatch from rest_framework import exceptions, renderers, views +from rest_framework.resolvers import url from rest_framework.response import Response from rest_framework.reverse import reverse from rest_framework.schemas import SchemaGenerator @@ -260,7 +260,7 @@ class SimpleRouter(BaseRouter): view = viewset.as_view(mapping, **route.initkwargs) name = route.name.format(basename=basename) - ret.append(url(regex, view, name=name)) + ret.append(url(regex, view, name=name, router=self)) return ret @@ -356,7 +356,7 @@ class DefaultRouter(SimpleRouter): if self.include_root_view: 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) if self.include_format_suffixes: