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

下图描述有误,匹配后

callback为完整路径, callback_args为浏览器url传递进的参数

比如url.py规定 re_path('/user/(\d+)')

如访问url为 http://192.168.0.1:8000:/user/123

callback为路经所在内存地址, args为123

现在具体观察这个方法

这里分成两部分查看

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的返回值

day-3 路由底层源码的更多相关文章

  1. 7月3日下午 微擎芸众商城 设计思路 - laravel路由底层源码解读

    学习参考文章 https://learnku.com/articles/13622/the-principle-of-laravel-routing-execution <?phpnamespa ...

  2. BAT资深工程师 由浅入深分析 Tp5&Tp6底层源码 - 分享

    BAT资深工程师由浅入深分析Tp5&Tp6底层源码 第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的 ...

  3. BAT资深工程师由浅入深分析Tp5&Tp6底层源码☆

    第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的帮助. 第2章 [TP5灵魂]自动加载Loader 深度分析 ...

  4. Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  5. 为什么很多类甚者底层源码要implements Serializable ?

    为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...

  6. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  7. List-ArrayList集合基础增强底层源码分析

    List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...

  8. 从底层源码浅析Mybatis的SqlSessionFactory初始化过程

    目录 搭建源码环境 POM依赖 测试SQL Mybatis全局配置文件 UserMapper接口 UserMapper配置 User实体 Main方法 快速进入Debug跟踪 源码分析准备 源码分析 ...

  9. Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap

    声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...

  10. 2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析

    介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博 ...

随机推荐

  1. MySQL MHA信息的收集【Filebeat+logstash+MySQL】

    一.项目背景 随着集团MHA集群的日渐增长,MHA管理平台话越来越迫切.而MHA平台的建设第一步就是将这些成百上千套的MHA集群信息收集起来,便于查询和管理. MHA主要信息如下: (1)基础配置信息 ...

  2. JavaScript 发布-订阅设计模式实现 React EventBus(相当于vue的$Bus)非父子之间通信

    提前声明: 我没有对传入的参数进行及时判断而规避错误,仅仅对核心方法进行了实现: 解决了react的非父子间的通信: 参考文档:https://github1s.com/browserify/even ...

  3. Spring的Factories机制介绍

    Java 的 SPI 机制 Java SpringBoot 加载 yml 配置文件中字典项 Spring的Factories就是Spring版本的Java Spi. Spring Factories的 ...

  4. DRF的限流组件(源码分析)

    DRF限流组件(源码分析) 限流,限制用户访问频率,例如:用户1分钟最多访问100次 或者 短信验证码一天每天可以发送50次, 防止盗刷. 对于匿名用户,使用用户IP作为唯一标识. 对于登录用户,使用 ...

  5. vue导入Excel数据并展示成表格

    前言: 用到的库参考链接: FileReader:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader    这个在之前的下载exce ...

  6. flink HelloWorld 之词频统计

    最近也在跟着学习flink,也是费了一点功夫才把开发环境都搭建了起来,做了一个简单的词频统计的demo- 准备工作 首先我们需要搭建需要的flink开发环境,我这里使用的是IDEA作为我的开发工具,所 ...

  7. Python_15 ddt驱动与日志

    一.查缺补漏 1. 在测试报告中添加注释,写在类名下面就行,方法名下面,三引号 2. 直接import ddt引用的时候需要ddt.ddt, ddt.data, ddt.unpack from ddt ...

  8. 波场(Tron) 网页版钱包开源

    之前做区块链项目太难了,很多组件.工具没有开源项目,需要自己写很麻烦. 我整理了几个自己给公司开发项目的时候,分离出来的几个工具,已经上传到 Gihub 了,感觉浏览量还行,在这里给园子里的朋友分享下 ...

  9. 2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被

    2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被 ...

  10. 2021-07-27:给定一个数组arr,长度为N,arr中的值只有1,2,3三种。arr[i] == 1,代表汉诺塔问题中,从上往下第i个圆盘目前在左;arr[i] == 2,代表汉诺塔问题中,从上

    2021-07-27:给定一个数组arr,长度为N,arr中的值只有1,2,3三种.arr[i] == 1,代表汉诺塔问题中,从上往下第i个圆盘目前在左:arr[i] == 2,代表汉诺塔问题中,从上 ...