day-3 路由底层源码

发布时间 2023-07-11 16:27:33作者: khalil12138

1. 定义路由本质

比如在url.py定义以下路由,浏览器中输入http://192.168.0.1:8000/user/2003-04-21可以访问

意味着此url http://192.168.0.1:8000/user/2003-04-21url.py里的路由们做了路由匹配

如果匹配成功找到相应的试图函数

 

 源码解析

ctrl+鼠标左键 点进re_path,会发现

如果re_path = partial(....)

那么上面的url re_path() = partial(), 这里的_path 和Pattern代表什么接着往后看

 partial偏函数:

作用:_path()里面规定了要传递一下参数,而path = partial(...)里面传递了Pattern=RegxPatten

那么我们在使用时即不需要再次传递Pattern


 点击_path 恍然大悟,_path接收route, view, kwargs, name,Pattern

route view 在url.py已经规定好了, Pattren在partial函数中规定好了

那么这里url.py里的re_path函数就可以写成

partial(_path(route, view, kwargs=None, name=None, Pattern=None), Pattern=RegexPattern)
替换掉route 和 view
partial(_path(r'user/(\d{4})-(\d{2})-(\d{2})', view.user, kwargs=None, name=None, Pattern=None), Pattern=RegexPattern)
因为partial是偏函数,最后路由变成
_path(r'user/(\d{4})-(\d{2})-(\d{2})', view.user, kwargs=None, name=None, Pattern=RegexPattern)

 

点进_path看看这个函数干啥呢

现在这是我们的路由 

re_path(r'user/(\d{4})-(\d{2})-(\d{2})', view.user)就变成了下面这样

URLPattern(Pattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True), view.user, None, None),

因为规定Pattern = RegxPattern

URLPattern(RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True), view.user, None, None),

 

两个类的关系 URLPattern RegexPattern

URLPattern默认接受四个参数并封装

 封装后的

self.pattern = RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True)

self.callback = view.user

其他为None

 

最后到了RegxPattern类,这里会去封装self._regex

上面传递了RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True)

那么self._regex= r'user/(\d{4})-(\d{2})-(\d{2})'

 

两层封装结束,现在

URLPattern.pattern._regex = r'user/(\d{4})-(\d{2})-(\d{2})'

self.callback = view.user

2.路由匹配流程

-启动项目

-请求到来

http://127.0.0.1:8000/user/

与定义好的路由逐一匹配

那么路由是怎么找到的呢

wsgi请求入口

往下找到wsgiHandler函数里的__call__方法,

此函数为类方法入口

environ为每次请求时浏览器携带的参数

request = self.request_class(environ)
因为规定
request_class = WSGIRequest
所以
request = WSGIRequest(environ)

 

 封装好后可以通过request.POST request.GET request.method request.FILES 拿到想要的数据

request.path_info 可以拿到地址

比如 https://192.168.0.1:8000/user/, path_info 可以拿到/user/

 

下一步通过request 进行函数处理拿到response, 点进get_response

点进get_response发现又进行了_middleware_chain处理

 

 再点 _middleware_chain = handler

 

 往上翻找handler到底是什么

 

 传入的mw_instance 

mw_instance = middleware(adapted_handler)

 

 又绕回到上面的adapt_method_mode方法

所以adapted_handler = handler

 

 

 现在确定handler就是_get_response

 

 

 现在具体观察这个方法

 

 这里分成两部分查看

1. get_resolver()

 进一步查看_get_cached_resolver(urlconf)

 

 URlResolver分析完毕,下面看URLResolver里的resolve方法, 图片注释有误

 

 

 

import_module相当于 from day006 import urls

urls.py被导入之后,patterns = urls.urlpatterns

然后就可进行循环

从最开始的讲解

urls.py里的每一条数据

比如 path('user/(\d{4})-(\d{2})-(\d{2})', view.user)也就等于

URLPattern(RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True), view.user, None, None),

 每次for pattern做匹配的时候也就是相当于

URLPattern(RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True), view.user, None, None),

找到它下面的resolve方法 传入'user/'做验证

这里的resolve就在URLPattern.resolve(new_path)

 

 因为一个re_path() = URLPattern(RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})', name=None, is_endpoint=True), view.user, None, None),

URLPattern()这里传递的第一个参数为RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})'

所以self.pattern = RegxPattern(r'user/(\d{4})-(\d{2})-(\d{2})'

 

 

 这里return的返回值