From 24fa728a476a6da3e565dbe33959ea62c02c250b Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Thu, 22 Dec 2016 00:54:15 +0300 Subject: Fixed #27612 -- Added a check for duplicate URL instance namespaces. --- django/core/checks/urls.py | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'django') diff --git a/django/core/checks/urls.py b/django/core/checks/urls.py index a1e9929084..8187a4e561 100644 --- a/django/core/checks/urls.py +++ b/django/core/checks/urls.py @@ -1,9 +1,11 @@ from __future__ import unicode_literals +from collections import Counter + from django.conf import settings from django.utils import six -from . import Error, Tags, register +from . import Error, Tags, Warning, register @register(Tags.urls) @@ -28,6 +30,43 @@ def check_resolver(resolver): return [] +@register(Tags.urls) +def check_url_namespaces_unique(app_configs, **kwargs): + """ + Warn if URL namespaces used in applications aren't unique. + """ + if not getattr(settings, 'ROOT_URLCONF', None): + return [] + + from django.urls import get_resolver + resolver = get_resolver() + all_namespaces = _load_all_namespaces(resolver) + counter = Counter(all_namespaces) + non_unique_namespaces = [n for n, count in counter.items() if count > 1] + errors = [] + for namespace in non_unique_namespaces: + errors.append(Warning( + "URL namespace '{}' isn't unique. You may not be able to reverse " + "all URLs in this namespace".format(namespace), + id="urls.W005", + )) + return errors + + +def _load_all_namespaces(resolver): + """ + Recursively load all namespaces from URL patterns. + """ + url_patterns = getattr(resolver, 'url_patterns', []) + namespaces = [ + url.namespace for url in url_patterns + if getattr(url, 'namespace', None) is not None + ] + for pattern in url_patterns: + namespaces.extend(_load_all_namespaces(pattern)) + return namespaces + + def get_warning_for_invalid_pattern(pattern): """ Return a list containing a warning that the pattern is invalid. -- cgit v1.3