成年大片免费视频播放二级_早上躁晚上躁天天躁8090_新金瓶梅2下载_欧美国产一卡二在线播放_国产在线精品欧美日韩电影

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Django url 路由匹配過(guò)程詳解

【字號(hào): 日期:2024-09-13 18:35:43瀏覽:58作者:豬豬
1 Django 如何處理一個(gè)請(qǐng)求

當(dāng)一個(gè)用戶(hù)請(qǐng)求Django 站點(diǎn)的一個(gè)頁(yè)面,下面是Django 系統(tǒng)決定執(zhí)行哪個(gè)Python 代碼使用的算法:

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

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() 實(shí)例的序列(sequence)。其實(shí)就是我們寫(xiě)的 url.py

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

一旦有 URL 匹配成功,Django 導(dǎo)入并調(diào)用相關(guān)的視圖,這個(gè)視圖是一個(gè)Python 函數(shù)(或基于類(lèi)的視圖 class-based view )。匹配成功會(huì)返回一個(gè)ResolverMatch對(duì)象。

如果沒(méi)有 URL 被匹配,或者匹配過(guò)程中出現(xiàn)了異常,Django 會(huì)調(diào)用一個(gè)適當(dāng)?shù)腻e(cuò)誤處理視圖。

本文詳述 2、3,即 urlpatterns 相關(guān)概念和路由匹配的過(guò)程。

2 URL 配置文件

在 Django 2 之后通常會(huì)使用 path/re_path 來(lái)設(shè)置路由,還要一個(gè)比較特殊的方法 include 。

path: 用于普通路徑 re_path:用于正則路徑 include: 將一個(gè)子 url 配置文件導(dǎo)入

如下示例:

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

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

2.1 path、re_path

設(shè)置路由的幾個(gè)函數(shù)均定義在 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)

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

第一個(gè)分支 如果綁定的是一個(gè) list或者tuple,使用 URLResolver 去解析,其實(shí)此時(shí)就是使用了 include 來(lái)定義 urlpattern。另外一種情況如果綁定的 view 是可以調(diào)用的,那就使用 URLPattern 去解析。URLPattern 中的 pattern 參數(shù)就是根據(jù)是采用 path/re_path 方法分別對(duì)應(yīng) 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 方法所做的工作就是通過(guò) import_module 將定義的 url 模塊導(dǎo)入。返回一個(gè)由子 urlconf 模塊、app_name、命名空間 namespace 組成的元組。回到剛剛上面的 _path 中第一個(gè)分支。將這個(gè)元組里面參數(shù)代入 URLResolver 并返回。

3 URLPattern 與 URLResolver3.1 URLPattern

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

class URLPattern: def __init__(self, pattern, callback, default_args=None, name=None): # 需要匹配的 urlpattern,這里根據(jù)是path還是re_path 分別是 RoutePattern或RegexPattern的實(shí)例 self.pattern = pattern self.callback = callback # the view self.default_args = default_args or {} self.name = name ... def resolve(self, path): 調(diào)用 RoutePattern 或 RegexPattern 的實(shí)例中的 match 方法進(jìn)行匹配(注意這里不是 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 初始化時(shí)其中的 pattern 就是根據(jù)是使用 path/re_path 分別對(duì)應(yīng)RoutePattern或RegexPattern。其實(shí)就是指定匹配的模式是普通路由還是正則的路由。

3.2 URLResolver

URLResolver 源碼中比較核心的是 resolve 函數(shù),就是傳入一個(gè) path,進(jìn)行匹配。

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 # 如果匹配成功,則繼續(xù)匹配它的url_patterns for pattern in self.url_patterns:try: # 這個(gè)pattern可能是URLPattern,也可能是URLResolver;如果是URLPattern,匹配成功則返回ResolverMatch;如果是URLResolver,則會(huì)遞歸調(diào)用下去。 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 比較關(guān)鍵的邏輯在 循環(huán)匹配 pattern 過(guò)程,如果 pattern是URLPattern匹配成功直接返回ResolverMatch,如果是另一個(gè)URLResolver,則實(shí)現(xiàn)了遞歸調(diào)用。

Django url 路由匹配過(guò)程詳解

Django 就是通過(guò)這個(gè) URLResolver 實(shí)現(xiàn)了多級(jí) URL 配置。

4 總結(jié)

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

本文從全局的角度大致說(shuō)明了Django路由的匹配流程,后續(xù)將從細(xì)節(jié)部分說(shuō)明其中的一些關(guān)鍵點(diǎn)。

到此這篇關(guān)于Django url 路由匹配過(guò)程詳解的文章就介紹到這了,更多相關(guān)Django url 路由匹配內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Django
相關(guān)文章: