Django URL-Patterns:如何检查所有 url 名称是否不同?

问题描述 投票:0回答:6

我想检查我的 django 项目中 url 模式的所有名称是否不同。

我不想不小心使用同一个名字两次。

django testing
6个回答
6
投票

安装

django-extensions
并运行以下命令:

python manage.py show_urls

它将向您显示应用程序中的所有网址

计算名称出现次数:

python manage.py show_urls -f verbose|grep 'URL Name' | sort | uniq -c 

https://github.com/django-extensions/django-extensions


3
投票

这是支持命名空间的版本:

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

2
投票
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

0
投票

只需确保目录 /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


0
投票

如果你将项目很好地构建成小的单独的django应用程序,那么这样的测试可能是“不必要的”,这样每个应用程序的路径都可以轻松监督。

查看 James Bennett 在 DjangoCon 2008 上制作的

这张很棒的幻灯片,了解关于何时引入新应用程序以及如何构建项目的一些想法。


0
投票
我的更强大的版本:

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
    
© www.soinside.com 2019 - 2024. All rights reserved.