Django3.2 自動發現所有路由代碼詳解
1.需求
發現項目本地所有帶別名的URL,組成一個有序字典,方便後續調用;
定向排除部分URL,如Django自帶的 admin下的路由;
2.代碼實現
import re # 正則 from collections import OrderedDict # 創建有序字典 from django.conf import settings # 導入setting配置文件(獲取項目根路徑urls.py) from django.utils.module_loading import import_string # 字符串導入模塊 from django.urls import URLPattern, URLResolver # Django自定義的類,可以判斷當前URL是否為根路徑(URLPattern)或繼續向下分發(URLResolver ) def check_url_exclude(url): """ 排除一些特定的URL :param url: 待檢驗的URL :return: """ for regex in settings.AUTO_DISCOVER_EXCLUDE: #將要定向排除的URL(可包含正則) 按照列表的形式寫入配置文件 settings.AUTO_DISCOVER_EXCLUDE 下 if re.match(regex, url): return True """ 示例: AUTO_DISCOVER_EXCLUDE = [ '/admin/.*', '/login/', '/logout/', '/index/', ] """ def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict): """ 遞歸的去獲取URL :param pre_namespace: namespace前綴,用於拼接name :param pre_url: url前綴,用於拼接url :param urlpatterns: 路由關系列表 :param url_ordered_dict: 用於保存遞歸中獲取的所有路由 :return: """ for item in urlpatterns: if isinstance(item, URLPattern): # 已經是根網址,獲取name及url寫入url_ordered_dict if not item.name: # 沒有別名(name)的路由地址直接跳過 continue # 拼接路由別名(包含分發下來的namespace;如 "rbac:menu_list") if pre_namespace: name = "%s:%s" % (pre_namespace, item.name) else: name = item.name # 拼接路由地址URl(包含分發下來的上層路由;如 "/rbac/menu/list") url = pre_url + item.pattern.regex.pattern # 此時拼接的路由包含起止符號,如:/^rbac/^menu/list/$ url = url.replace("^", "").replace("$", "") # 刪除起止符:/rbac/menu/list/ # 排除一些特定的路由URL if check_url_exclude(url): # 調用check_url_exclude函數定向排除部分URL continue url_ordered_dict[name] = {"name": name, "url": url} elif isinstance(item, URLResolver): # 路由分發,遞歸操作 if pre_namespace: # 上次循環(上一層)分發是否包含namespace if item.namespace: # 本次循環(當前層)是否包含namespace namespace = "%s:%s" % (pre_namespace, item.namespace,) # 上層、當前層都包含直接拼接兩層的namespace else: namespace = pre_namespace # 當前層分發不包含namespace,直接用上一層的 else: if item.namespace: namespace = item.namespace # 上一層分發不包含namespace,直接使用當前層的 else: namespace = None # 上一層、當前層都沒有,直接定義層none recursion_urls(namespace, pre_url + item.pattern.regex.pattern, item.url_patterns, url_ordered_dict) # 遞歸繼續執行 def get_all_url_dict(): """ 獲取項目所有路由 :return: """ url_ordered_dict = OrderedDict() # 包含本項目所有權限URl的有序字典 md = import_string(settings.ROOT_URLCONF) # 配置文件內的 ROOT_URLCONF 為本項目根路由urls.py 的路徑(字符串),使用 import_string 用字符串加載模塊 recursion_urls(None, "/", md.urlpatterns, url_ordered_dict) # 調用 recursion_urls 函數獲取所有路由字典,根路徑下沒有namespace 定義為 None;沒有url前綴 定義為 / return url_ordered_dict
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- Django url 路由匹配過程詳解
- 使用gunicorn部署django項目的問題
- Django路由層如何獲取正確的url
- 利用Python創建第一個Django框架程序
- Django中url與path及re_path的區別說明