獲取 Django 項目下全部 URL,一個函數(shù)輕松搞定
廢話不多說,直接上代碼。
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 參數(shù)傳入相應前綴
for url, name in get_all_url(get_resolver('dashboard.urls')):
print("url='{}' name='{}'".format(url, name))
其中用到的函數(shù)就是 get_resolver,讓我們看看源碼,這個函數(shù)應該怎么用。
# 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)
傳入?yún)?shù) urlconf,參數(shù)有個默認值 settings.ROOT_URLCONF,打印出來是 myproject.urls,其實就是項目全局下的路由文件。
返回值是 URLResolver 類,這個類就比較復雜了,看了源碼也不是很明白應該怎么處理這個類。
# 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 相關的函數(shù)還是要特殊關照一下。
打印一下這個結(jié)果,看看有沒有發(fā)現(xiàn)。
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'>]
結(jié)果是一個列表,元素有兩種,分別是 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,而后者再遞歸調(diào)用也同樣可以拿到結(jié)果。
到這里就可以宣布大功告成了。
關注公眾號 AlwaysBeta,各種后端開發(fā)技術(shù)干貨。
題圖: Image by Rickson Bejar from Pixabay
參考文章:
https://www.ikaze.cn/article/60
大家都在看:
評論
圖片
表情
