成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Django url 路由匹配過程詳解

瀏覽:276日期:2024-09-13 18:35:43
1 Django 如何處理一個請求

當一個用戶請求Django 站點的一個頁面,下面是Django 系統決定執行哪個Python 代碼使用的算法:

Django 確定使用根 URLconf 模塊。通常,這是 ROOT_URLCONF 設置的值(即 settings 中的 ROOT_URLCONF),但如果傳入 HttpRequest 對象擁有 urlconf 屬性(通過中間件設置),它的值將被用來代替 ROOT_URLCONF 設置。可以在 django/core/handlers/base.py 發現該邏輯。

class BaseHandler: ... def _get_response(self, request): ... if hasattr(request, ’urlconf’): urlconf = request.urlconf set_urlconf(urlconf) resolver = get_resolver(urlconf) else: resolver = get_resolver()

Django 加載該 Python 模塊并尋找可用的 urlpatterns 。它是 django.urls.path() 和(或) django.urls.re_path() 實例的序列(sequence)。其實就是我們寫的 url.py

Django 會按順序遍歷每個 URL 模式,然后會在所請求的URL匹配到第一個模式后停止,并與 path_info 匹配。這個是路由匹配的關鍵,相關邏輯均在django/urls/resolvers.py。其中有幾個比較重要的概念,如RegexPattern、RoutePattern、URLPattern、URLResolver。其中URLResolver有嵌套的邏輯,下文詳述。

一旦有 URL 匹配成功,Django 導入并調用相關的視圖,這個視圖是一個Python 函數(或基于類的視圖 class-based view )。匹配成功會返回一個ResolverMatch對象。

如果沒有 URL 被匹配,或者匹配過程中出現了異常,Django 會調用一個適當的錯誤處理視圖。

本文詳述 2、3,即 urlpatterns 相關概念和路由匹配的過程。

2 URL 配置文件

在 Django 2 之后通常會使用 path/re_path 來設置路由,還要一個比較特殊的方法 include 。

path: 用于普通路徑 re_path:用于正則路徑 include: 將一個子 url 配置文件導入

如下示例:

urlpatterns = [ path(’index/’, views.index), # 普通路徑 re_path(r’^articles/([0-9]{4})/$’, views.articles), # 正則路徑 path('app01/', include('app01.urls')),]

上面的配置文件,設置了3條 urlpattern,分別是普通路徑 index/ 與 視圖函數 views.index,正則路徑 ^articles/([0-9]{4})/$ 與視圖函數 views.articles 綁定。app01/ 和app01.urls 綁定,app01.urls 不是一個視圖函數,而是一個子模塊的 urlpatterns。可以看到 urlpattern 可以把一個 url 和視圖函數綁定,也可以和一個子 urlpattern 進行綁定。

2.1 path、re_path

設置路由的幾個函數均定義在 django/urls/conf.py 中。

def include(arg, namespace=None): ... return (urlconf_module, app_name, namespace)def _path(route, view, kwargs=None, name=None, Pattern=None): if isinstance(view, (list, tuple)): # For include(...) processing. pattern = Pattern(route, is_endpoint=False) urlconf_module, app_name, namespace = view return URLResolver( pattern, urlconf_module, kwargs, app_name=app_name, namespace=namespace, ) elif callable(view): pattern = Pattern(route, name=name, is_endpoint=True) return URLPattern(pattern, view, kwargs, name) else: raise TypeError(’view must be a callable or a list/tuple in the case of include().’)path = partial(_path, Pattern=RoutePattern)re_path = partial(_path, Pattern=RegexPattern)

首先先來看下 path 和 re_path,這兩個函數分別被 functools 下面的 partial 封裝了一下。partial 的作用簡單來說就是將一個函數的某些參數給固定住,返回一個新的函數。詳細文檔可以查看partial 文檔。這樣就不難理解 path 和 re_path,他們就是就是綁定了不同的 Pattern 參數的 _path 函數。進一步查看 _path 內部的邏輯,

第一個分支 如果綁定的是一個 list或者tuple,使用 URLResolver 去解析,其實此時就是使用了 include 來定義 urlpattern。另外一種情況如果綁定的 view 是可以調用的,那就使用 URLPattern 去解析。URLPattern 中的 pattern 參數就是根據是采用 path/re_path 方法分別對應 RoutePattern/RegexPattern。

2.2 include

def include(arg, namespace=None): ... if isinstance(urlconf_module, str): urlconf_module = import_module(urlconf_module) patterns = getattr(urlconf_module, ’urlpatterns’, urlconf_module) app_name = getattr(urlconf_module, ’app_name’, app_name) ... return (urlconf_module, app_name, namespace)

include 方法所做的工作就是通過 import_module 將定義的 url 模塊導入。返回一個由子 urlconf 模塊、app_name、命名空間 namespace 組成的元組。回到剛剛上面的 _path 中第一個分支。將這個元組里面參數代入 URLResolver 并返回。

3 URLPattern 與 URLResolver3.1 URLPattern

上面提到如果url定義中綁定是一個可以直接調用的view。那就是使用URLPattern直接去解析。

class URLPattern: def __init__(self, pattern, callback, default_args=None, name=None): # 需要匹配的 urlpattern,這里根據是path還是re_path 分別是 RoutePattern或RegexPattern的實例 self.pattern = pattern self.callback = callback # the view self.default_args = default_args or {} self.name = name ... def resolve(self, path): 調用 RoutePattern 或 RegexPattern 的實例中的 match 方法進行匹配(注意這里不是 re 模塊里面的 match) match = self.pattern.match(path) if match: new_path, args, kwargs = match # Pass any extra_kwargs as **kwargs. kwargs.update(self.default_args) # 匹配成功返回 `ResolverMatch` return ResolverMatch(self.callback, args, kwargs, self.pattern.name, route=str(self.pattern)) ...

URLPattern 初始化時其中的 pattern 就是根據是使用 path/re_path 分別對應RoutePattern或RegexPattern。其實就是指定匹配的模式是普通路由還是正則的路由。

3.2 URLResolver

URLResolver 源碼中比較核心的是 resolve 函數,就是傳入一個 path,進行匹配。

class URLResolver: def resolve(self, path): path = str(path) # path may be a reverse_lazy object tried = [] # 匹配 path match = self.pattern.match(path) if match: new_path, args, kwargs = match # 如果匹配成功,則繼續匹配它的url_patterns for pattern in self.url_patterns:try: # 這個pattern可能是URLPattern,也可能是URLResolver;如果是URLPattern,匹配成功則返回ResolverMatch;如果是URLResolver,則會遞歸調用下去。 sub_match = pattern.resolve(new_path)...else: if sub_match: ... # 匹配成功返回ResolverMatch return ResolverMatch( sub_match.func, sub_match_args, sub_match_dict, sub_match.url_name, [self.app_name] + sub_match.app_names, [self.namespace] + sub_match.namespaces, self._join_route(current_route, sub_match.route), ) tried.append([pattern]) raise Resolver404({’tried’: tried, ’path’: new_path}) raise Resolver404({’path’: path})

URLResolver 比較關鍵的邏輯在 循環匹配 pattern 過程,如果 pattern是URLPattern匹配成功直接返回ResolverMatch,如果是另一個URLResolver,則實現了遞歸調用。

Django url 路由匹配過程詳解

Django 就是通過這個 URLResolver 實現了多級 URL 配置。

4 總結

Django 路由匹配的有幾個比較核心的概念 path/re_path/include、RegexPattern/RoutePattern、URLPattern/URLResolver。首先用 partial 封裝 _path,綁定了一個 pattern 匹配模式(RegexPattern/RoutePattern),后面多次用到了這個 pattern。然后就是根據 view 是元組還是可調用視圖函數,分別使用URLResolver和URLPattern去解析,這兩個類解析之后都會返回給ResolverMatch,由它去回調匹配成功后的結果(view和args等)。

本文從全局的角度大致說明了Django路由的匹配流程,后續將從細節部分說明其中的一些關鍵點。

到此這篇關于Django url 路由匹配過程詳解的文章就介紹到這了,更多相關Django url 路由匹配內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Django
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
不卡av电影在线播放| 99精品国产视频| 成人免费精品视频| 色婷婷综合久久久| 亚洲一区二区视频在线| 伊人久久亚洲热| 国产午夜亚洲精品理论片色戒| 国产成人亚洲精品青草天美| 欧美少妇一区二区| 日本v片在线高清不卡在线观看| 亚洲国产专区| 国产精品日韩精品欧美在线| 福利一区二区在线| 欧美高清视频在线高清观看mv色露露十八 | 日本不卡免费在线视频| 亚久久调教视频| 亚洲国产日韩精品| 亚洲一区黄色| 午夜精品福利一区二区三区av| 国产精品久久久一区二区三区| 亚洲乱码国产乱码精品精的特点| 狠狠久久综合婷婷不卡| 国产亚洲美州欧州综合国| 大桥未久av一区二区三区中文| 正在播放亚洲一区| 国产成人av福利| 日韩一区二区三区四区| 国产丶欧美丶日本不卡视频| 日韩久久精品一区| 国产91丝袜在线播放0| 欧美一二三区在线观看| 国产久卡久卡久卡久卡视频精品| 精品视频1区2区| 国产在线乱码一区二区三区| 欧美日韩一二三区| 精品一区免费av| 日韩一级二级三级精品视频| 成人性色生活片免费看爆迷你毛片| 日韩一级黄色片| 91亚洲国产成人精品一区二三| 国产日产欧美一区二区视频| 亚洲午夜视频| 玉米视频成人免费看| 免费亚洲电影| 美日韩一区二区三区| 欧美精品日韩综合在线| 99精品国产99久久久久久白柏 | 天使萌一区二区三区免费观看| 色综合久久久久| 国产一区二区三区免费| 日韩精品一区二区三区蜜臀| www.久久久久久久久| 国产精品久久久久影院| 国产农村妇女精品一二区| 蜜臀av在线播放一区二区三区| 在线播放欧美女士性生活| 成人av在线资源网| 中文字幕在线观看不卡视频| aa亚洲婷婷| 麻豆精品国产传媒mv男同 | 欧美色手机在线观看| 国产经典欧美精品| 久久婷婷国产综合国色天香| 国产在线精品一区二区中文| 一区二区三区小说| 欧美片网站yy| 欧美日韩1区| 午夜精品久久一牛影视| 日韩午夜电影av| 激情视频一区二区| 蜜臀久久99精品久久久久宅男| 精品免费视频一区二区| 亚洲国产专区校园欧美| 麻豆91精品91久久久的内涵| www欧美成人18+| 国产精品久久久一区二区三区| 国产一区二区三区四区五区美女| 国产欧美视频一区二区| 国产午夜精品一区二区三区欧美 | 久久婷婷丁香| 成人毛片在线观看| 亚洲毛片av在线| 在线电影国产精品| 精品999网站| 黄一区二区三区| 中文字幕五月欧美| 91久久精品一区二区三| www.爱久久.com| 午夜免费欧美电影| 欧美成人国产一区二区| 国产精品一区二区三区观看| 国产成人免费在线视频| 亚洲蜜臀av乱码久久精品蜜桃| 欧美系列亚洲系列| 国产在线视频欧美一区二区三区| 蜜臀久久久99精品久久久久久| 中文字幕欧美国产| 欧美视频在线一区| 国产一区观看| 国内精品国产三级国产a久久| 亚洲天天做日日做天天谢日日欢| 欧美日韩国产成人在线91| 国产精品jizz在线观看美国| 久久国产精品一区二区| 国产精品青草久久| 国产精品日日摸夜夜摸av| 欧美日韩一二区| 日韩午夜免费视频| 成人av在线电影| 日产国产高清一区二区三区| 国产精品欧美一区喷水| 51午夜精品国产| 中文精品视频一区二区在线观看| 成人免费看的视频| 免费观看成人鲁鲁鲁鲁鲁视频| 中文字幕一区二区三| 日韩免费性生活视频播放| 亚洲一区二区三区高清| 99久久伊人精品| 久久99精品久久久久久国产越南| 亚洲同性gay激情无套| 精品国产露脸精彩对白| 欧洲精品一区二区| 在线综合亚洲| 欧美午夜国产| 国产色91在线| 日韩一级大片在线| 色婷婷综合久久久久中文一区二区| 红桃视频亚洲| 丁香桃色午夜亚洲一区二区三区| 天天免费综合色| 亚洲欧美aⅴ...| 国产视频不卡一区| 日韩免费一区二区三区在线播放| 欧美最猛性xxxxx直播| 中文精品视频一区二区在线观看| 欧美日本亚洲| 91欧美激情一区二区三区成人| 国产一区二区在线看| 三级久久三级久久| 一区二区三区资源| 国产精品国产三级国产| 久久婷婷色综合| 日韩色视频在线观看| 欧美吞精做爰啪啪高潮| 久久一区免费| 久久国产毛片| 在线欧美亚洲| 欧美色欧美亚洲另类七区| 成人黄色软件下载| 国产成人在线免费| 韩国精品在线观看| 麻豆国产欧美一区二区三区| 亚洲6080在线| 亚洲成年人网站在线观看| 亚洲午夜久久久久久久久电影院| 18成人在线观看| 国产精品福利一区| 国产精品天天看| 国产清纯在线一区二区www| 欧美精品一区二区久久久| 欧美一区二区免费观在线| 欧美日韩精品欧美日韩精品一 | 精品国产在天天线2019| 51精品秘密在线观看| 欧美日韩黄色影视| 欧美日韩国产欧美日美国产精品| 色婷婷综合中文久久一本| 色婷婷综合久色| 色婷婷av一区二区三区gif| 久久久久久色| 免费久久久一本精品久久区| 国产日韩亚洲| 国产精品久久亚洲7777| 国产精品日韩高清| 国产精品老牛| 久久蜜桃精品| 在线观看日韩国产| 欧美精三区欧美精三区| 欧美一区二区三区四区高清| 欧美日韩免费高清一区色橹橹 | 国产精品福利影院| 亚洲精品视频免费看| 亚洲国产va精品久久久不卡综合| 首页欧美精品中文字幕| 美国毛片一区二区| 国模大尺度一区二区三区| 国产丶欧美丶日本不卡视频| 成人爽a毛片一区二区免费| 国产精品系列在线观看| 粉嫩一区二区三区性色av| 不卡的看片网站| 91蝌蚪porny成人天涯| 欧美成人有码| 亚洲国产欧美日韩| 免费视频一区二区三区在线观看| 日本道色综合久久| 69堂国产成人免费视频| 日韩免费福利电影在线观看| 久久―日本道色综合久久|