日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

Django url 路由匹配過程詳解

瀏覽:316日期: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
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美亚洲免费| 亚洲精品影院在线观看| 日本a级不卡| 亚久久调教视频| 日韩欧乱色一区二区三区在线| 久久国产88| 亚洲精品无播放器在线播放| 亚洲最新av| 日本va欧美va精品发布| 国产亚洲高清在线观看| 国产欧美一区二区三区米奇| 午夜久久av| 国产日本精品| 国产精品第一| 国产乱码午夜在线视频| 久久青草久久| 国产精品丝袜xxxxxxx| 久久性天堂网| 国产一卡不卡| 麻豆极品一区二区三区| 国产精品伦理久久久久久| 色婷婷精品视频| 99成人在线| 天堂久久一区| 免费亚洲婷婷| 色88888久久久久久影院| 久久久国产精品一区二区中文| 欧美日韩精品一本二本三本 | 欧美韩一区二区| 国产不卡一区| 日韩午夜黄色| 国产欧美一区二区精品久久久| 久久精品国产亚洲aⅴ| 欧产日产国产精品视频| 9久re热视频在线精品| 日韩福利在线观看| 精品国产乱码久久久| 婷婷综合六月| 亚州av一区| 色在线中文字幕| 日韩精品一二三区| 精品一级视频| 国产精品日韩欧美一区| 国产精品久久久久久妇女| 久久久噜噜噜| 国产视频一区二| 欧美亚洲激情| 日韩激情啪啪| 久久久久中文| 欧美日韩一区二区三区四区在线观看 | 午夜国产精品视频| 欧美亚洲免费| 亚洲小说欧美另类婷婷| 日韩国产精品久久久久久亚洲| 中文在线资源| 日韩av中文字幕一区二区 | 色8久久久久| 久久精品国产999大香线蕉| 亚洲手机在线| 国产精品亚洲综合色区韩国| 国产字幕视频一区二区| 国产日韩中文在线中文字幕| 免费黄色成人| 精品黄色一级片| 蜜臀久久99精品久久久画质超高清| 精品国产a一区二区三区v免费| 蜜桃久久久久久| 中文在线中文资源| 日本欧美在线| 欧美福利专区| 美女在线视频一区| 中文字幕亚洲影视| 成人啊v在线| 欧美三区不卡| 三级一区在线视频先锋| 亚洲国产欧美日本视频| 欧美亚洲tv| 亚洲少妇在线| 亚洲成人不卡| 精品亚洲成人| 日精品一区二区三区| 狠狠干成人综合网| 蜜臀国产一区| 韩日一区二区| 国产毛片精品| 亚洲日韩中文字幕一区| 激情欧美亚洲| 国产aⅴ精品一区二区四区| 四虎精品一区二区免费| 亚洲激情av| 亚洲精品一级二级| 精品深夜福利视频| 国产亚洲电影| 日韩av中文在线观看| 久久国产成人| 亚洲黄页一区| 亚洲一本视频| 播放一区二区| 亚洲区欧美区| 欧美手机在线| 女生影院久久| 国产精品视频一区二区三区四蜜臂 | 乱人伦精品视频在线观看| 91精品蜜臀一区二区三区在线 | 四虎4545www国产精品| 精品视频一区二区三区四区五区| 欧美午夜网站| 日本在线不卡视频| 蜜桃视频一区二区| 美女网站久久| 蜜臀久久久久久久| 日韩专区在线视频| 蜜臀av亚洲一区中文字幕| 一本色道精品久久一区二区三区| 日韩免费视频| 国产精品久久久久久久久妇女| 精品国产亚洲一区二区在线观看| 久久99精品久久久久久园产越南 | 日韩欧美三区| 亚洲免费中文| 久久成人一区| 亚洲精品国产精品粉嫩| 亚洲综合小说| 一区二区国产在线观看| 国产一区精品福利| 欧美一区激情| 亚洲综合色婷婷在线观看| 亚洲午夜黄色| 久久国产小视频| 亚洲午夜黄色| 伊人久久大香线蕉av不卡| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 欧美成a人国产精品高清乱码在线观看片在线观看久| 精品中文字幕一区二区三区| 丰满少妇一区| 久久蜜桃精品| 免费欧美日韩| 少妇精品久久久一区二区| 亚洲精品大片| 国产剧情在线观看一区| 国产精品天天看天天狠| 国产精品久久久久毛片大屁完整版| 国产精品男女| 久久高清一区| 日本欧美在线| 精品国产一区二区三区av片| 92国产精品| 婷婷综合社区| 美女久久一区| 人人爱人人干婷婷丁香亚洲| 国产伦精品一区二区三区千人斩 | 久久免费精品| 三级在线看中文字幕完整版| 欧美91福利在线观看| 午夜久久黄色| 亚洲精品乱码久久久久久蜜桃麻豆| 国产日韩一区二区三区在线| 国产不卡人人| 午夜在线精品| 欧美日韩午夜电影网| 精品久久久网| 亚州av乱码久久精品蜜桃| 日韩在线视频一区二区三区| 免费一级欧美片在线观看网站| 久久久久网站| 亚洲bt欧美bt精品777| 美女视频黄久久| 欧美精品一区二区久久| 欧美一级二级三级视频| 久久久久97| 国产综合亚洲精品一区二| 亚洲综合激情在线| 国产一区二区三区久久| 亚洲欧美高清| 精品欠久久久中文字幕加勒比| 亚洲国产日韩欧美在线| 欧美性www| 午夜精品亚洲| 久久69成人| 亚洲欧美久久| 水蜜桃久久夜色精品一区| 最新亚洲国产| 日韩免费福利视频| 日韩精品久久久久久久软件91| 国产999精品在线观看| 免费人成黄页网站在线一区二区 | 你懂的国产精品永久在线| 激情欧美丁香| 国产精品欧美日韩一区| 女人天堂亚洲aⅴ在线观看| 国产精品一区二区av交换| 国产99精品一区| 欧美日韩一区自拍| 亚洲网站视频| 欧美1区2区3| 免费在线观看日韩欧美| 日韩欧美午夜| 国产精品成人自拍| 中日韩男男gay无套| 成人美女视频|