廢話很少說,直接上代碼。python
from django.urls import get_resolver, URLPattern, URLResolver
def get_all_url(resolver=None, pre='/'):
if resolver is None:
resolver = get_resolver()
for r in resolver.url_patterns:
if isinstance(r, URLPattern):
if '<pk>' in str(r.pattern):
continue
yield pre + str(r.pattern).replace('^', '').replace('$', ''), r.name
if isinstance(r, URLResolver):
yield from get_all_url(r, pre + str(r.pattern))
if __name__ == '__main__':
# 獲取項目所有 url
for url, name in get_all_url():
print("url='{}' name='{}'".format(url, name))
# 獲取某個 app 下的所有 url
# 假設有一個 app 叫 dashboard
# 經過 pre 參數傳入相應前綴
for url, name in get_all_url(get_resolver('dashboard.urls')):
print("url='{}' name='{}'".format(url, name))
複製代碼
其中用到的函數就是 get_resolver
,讓咱們看看源碼,這個函數應該怎麼用。django
# django/urls/resolvers.py
def get_resolver(urlconf=None):
if urlconf is None:
urlconf = settings.ROOT_URLCONF
return _get_cached_resolver(urlconf)
@functools.lru_cache(maxsize=None)
def _get_cached_resolver(urlconf=None):
return URLResolver(RegexPattern(r'^/'), urlconf)
複製代碼
傳入參數 urlconf
,參數有個默認值 settings.ROOT_URLCONF
,打印出來是 myproject.urls
,其實就是項目全局下的路由文件。後端
返回值是 URLResolver
類,這個類就比較複雜了,看了源碼也不是很明白應該怎麼處理這個類。api
# django/urls/resolvers.py
class URLResolver:
# 省略了一堆代碼
@cached_property
def urlconf_module(self):
if isinstance(self.urlconf_name, str):
return import_module(self.urlconf_name)
else:
return self.urlconf_name
@cached_property
def url_patterns(self):
# urlconf_module might be a valid set of patterns, so we default to it
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
try:
iter(patterns)
except TypeError as e:
msg = (
"The included URLconf '{name}' does not appear to have any "
"patterns in it. If you see valid patterns in the file then "
"the issue is probably caused by a circular import."
)
raise ImproperlyConfigured(msg.format(name=self.urlconf_name)) from e
return patterns
複製代碼
不過仍是有一個方法引發了個人注意,畢竟咱們要取 url,那跟 url 相關的函數仍是要特殊關照一下。markdown
打印一下這個結果,看看有沒有發現。app
print(get_resolver('myproject.urls').url_patterns)
# 輸出
# [
# ...
# <URLPattern 'api/v1/api-doc' [name='api-doc']>,
# <URLResolver <URLPattern list> (api-docs:api-docs) # 'api/v1/drf-api-doc'>]
複製代碼
結果是一個列表,元素有兩種,分別是 URLPattern
類和 URLResolver
類。函數
# django/urls/resolvers.py
class URLPattern:
def __init__(self, pattern, callback, default_args=None, name=None):
self.pattern = pattern
self.callback = callback # the view
self.default_args = default_args or {}
self.name = name
複製代碼
前者能夠直接就拿 self.pattern
就是對應 url,然後者再遞歸調用也一樣能夠拿到結果。oop
到這裏就能夠宣佈大功告成了。ui
關注公衆號 AlwaysBeta,各類後端開發技術乾貨。url
參考文章: