我想检查我的 django 项目中 url 模式的所有名称是否不同。
我不想不小心使用同一个名字两次。
安装
django-extensions
并运行以下命令:
python manage.py show_urls
它将向您显示应用程序中的所有网址
计算名称出现次数:
python manage.py show_urls -f verbose|grep 'URL Name' | sort | uniq -c
这是支持命名空间的版本:
def test_url_name_not_duplicate(self):
resolver = urlresolvers.get_resolver(None)
names=defaultdict(list)
for pattern, namespace in resolveutils.walk_url_patterns_with_namespace(resolver.url_patterns):
if not pattern.name:
continue
name=pattern.name
if namespace:
name='%s:%s' % (namespace, name)
if pattern.regex.groupindex:
name='%s %s' % (name, sorted(pattern.regex.groupindex.keys()))
names[name].append(pattern)
duplicates=dict([(name, patterns) for name, patterns in names.items() if len(patterns)>1 and name not in ['login', 'logout']])
self.assertFalse(duplicates, 'url patterns with duplicate names exist:\n%s' % '\n'.join(['url_name "%s":\n%s\n' % (
name, '\n'.join([' %s %s %s' % (pattern.regex.pattern, pattern.callback, inspect.getsourcefile(pattern.callback)) for pattern in patterns]))
for name, patterns in sorted(duplicates.items())]))
以及辅助方法:
def walk_url_patterns_with_namespace(patterns, namespace=''):
for pattern in patterns:
if hasattr(pattern, 'url_patterns'): # RegexURLResolver
if namespace:
namespace='%s:%s' % (namespace, pattern.namespace)
for pattern, namespace in walk_url_patterns_with_namespace(pattern.url_patterns, namespace):
yield pattern, namespace
else: # RegexURLPattern
yield pattern, namespace
def test_url_name_not_duplicate(self):
resolver = urlresolvers.get_resolver(None)
names=defaultdict(list)
for pattern in resolveutils.walk_url_patterns(resolver.url_patterns):
if not pattern.name:
continue
names[pattern.name].append(pattern)
duplicates=dict([(name, patterns) for name, patterns in names.items() if len(patterns)>1])
self.assertFalse(duplicates, 'url patterns with duplicate names exist:\n%s' % '\n'.join(['url_name "%s":\n%s\n' % (
name, '\n'.join([' %s %s %s' % (pattern.regex.pattern, pattern.callback, inspect.getsourcefile(pattern.callback)) for pattern in patterns])) for name, patterns in sorted(duplicates.items())]))
辅助方法 walk_url_patterns()
def walk_url_patterns(patterns):
for pattern in patterns:
if hasattr(pattern, 'url_patterns'):
for pattern in walk_url_patterns(pattern.url_patterns):
yield pattern
else:
yield pattern
如果存在重复则输出:
url_name "myquery":
^myquery/$ <function myquery> /home/user/src/foo/foo/views/query.py
^query/$ <function myquery> /home/user/src/foo/foo/views/query.py
url_name "bla":
^bla/$ <function bla> /home/user/src/foo/foo/views/bla.py
^bla2/$ <function bla2> /home/user/src/foo/foo/views/bla2.py
只需确保目录 /project_name/project_name/ 中的 urls.py 的行为如下:
url(r'^polls/', include('polls.urls', namespace="polls"))。
然后您的所有应用程序将使用不同的 url。在您的应用程序中:确保您的网址是这样的:
url(r'^下载/$',views.download,name='下载'),
url(r'^anotherurl/$',views.download,name='下载'),
所以所有的网址都会不同。事实上,我不喜欢将参数放入 url 中的方式,例如
/民意调查/问题/3/结果/
这将使两次使用同一个网址名称变得更加容易。我会这样改变它
/possl/问题/结果/?question_id=3
如果你将项目很好地构建成小的单独的django应用程序,那么这样的测试可能是“不必要的”,这样每个应用程序的路径都可以轻松监督。
查看 James Bennett 在 DjangoCon 2008 上制作的这张很棒的幻灯片,了解关于何时引入新应用程序以及如何构建项目的一些想法。
def walk_url_patterns_with_namespace(patterns, namespace=""):
for pattern in patterns:
if isinstance(pattern, URLResolver):
ns = (
f"{namespace}:{pattern.namespace}"
if pattern.namespace and namespace
else (pattern.namespace or namespace)
)
yield from walk_url_patterns_with_namespace(pattern.url_patterns, ns)
else:
yield pattern, namespace