flask源码分析
本flask源码分析不间断更新
而且我分析的源码全是我个人觉得是很漂亮的
1 flask-login
1.1 flask.ext.login.login_required(func),下面是它的文档的官方源码
def login_required(func):
'''
If you decorate a view with this, it will ensure that the current user is
logged in and authenticated before calling the actual view. (If they are
not, it calls the :attr:`LoginManager.unauthorized` callback.) For
example:: @app.route('/post')
@login_required
def post():
pass If there are only certain times you need to require that your user is
logged in, you can do so with:: if not current_user.is_authenticated:
return current_app.login_manager.unauthorized() ...which is essentially the code that this function adds to your views. It can be convenient to globally turn off authentication when unit testing.
To enable this, if the application configuration variable `LOGIN_DISABLED`
is set to `True`, this decorator will be ignored. :param func: The view function to decorate.
:type func: function
'''
@wraps(func)
def decorated_view(*args, **kwargs):
if current_app.login_manager._login_disabled:
return func(*args, **kwargs)
elif not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
其实这个login_required方法和我最开始认为的一样,就是用一个装饰器包裹着func,里面有一个对用户是否login有个判断,最后返回func。
1.1.1 根据官方文档可以看出,这个方法有两种使用方式
第一种是对装饰的func,也就是最常用的方式。
第二种是仅仅使用一次,用一次判断是否已authorize,要没有进行authorize。
1.1.2 下面具体分析
首先这个login_required的方法的基本方式就是:用装饰器包裹func,里面进行一次authorize,current_app.login_manager.unauthorized()。
然后说一下主要逻辑:如果用户login了,但没authorize,就进行authorize,如果没有login就返回原func。
其中current_app.login_manager._login_disabled这个函数的目的是:判断全局变量中LOGIN_DISABLE是否为真,而这个函数的目的是控制这个装饰器是否生效。
2 flask的route方法,基于flask0.1最初版本
到目前还没有看过werkzeug的源码,所以有些不足以后补充
首先是route方法的源码:
def route(self, rule, **options):
"""A decorator that is used to register a view function for a
given URL rule. Example:: @app.route('/')
def index():
return 'Hello World' Variables parts in the route can be specified with angular
brackets (``/user/<username>``). By default a variable part
in the URL accepts any string without a slash however a different
converter can be specified as well by using ``<converter:name>``. Variable parts are passed to the view function as keyword
arguments. The following converters are possible: =========== ===========================================
`int` accepts integers
`float` like `int` but for floating point values
`path` like the default but also accepts slashes
=========== =========================================== Here some examples:: @app.route('/')
def index():
pass @app.route('/<username>')
def show_user(username):
pass @app.route('/post/<int:post_id>')
def show_post(post_id):
pass An important detail to keep in mind is how Flask deals with trailing
slashes. The idea is to keep each URL unique so the following rules
apply: 1. If a rule ends with a slash and is requested without a slash
by the user, the user is automatically redirected to the same
page with a trailing slash attached.
2. If a rule does not end with a trailing slash and the user request
the page with a trailing slash, a 404 not found is raised. This is consistent with how web servers deal with static files. This
also makes it possible to use relative link targets safely. The :meth:`route` decorator accepts a couple of other arguments
as well: :param rule: the URL rule as string
:param methods: a list of methods this rule should be limited
to (``GET``, ``POST`` etc.). By default a rule
just listens for ``GET`` (and implicitly ``HEAD``).
:param subdomain: specifies the rule for the subdoain in case
subdomain matching is in use.
:param strict_slashes: can be used to disable the strict slashes
setting for this rule. See above.
:param options: other options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object.
"""
def decorator(f):
self.add_url_rule(rule, f.__name__, **options)
self.view_functions[f.__name__] = f
return f
return decorator
注释部分主要是使用方法不过多说明
2.1.1 分析装饰器
它的装饰器用的很巧妙,装饰器的wraper传入的是参数,而inner传入的是func, 所以在inner函数内部会返回func
2.1.2 内部主要方法
add_url_rule(rule, f.__name__, **options) 这个方法主要是将route的路由和option进行注册
view_functions[f.__name__] 就是在view_function字典中添加这个route的函数名
2.2 add_url_rule 方法
说道注册路由就不得不提这个方法了,首先展示一下源码
def add_url_rule(self, rule, endpoint, **options):
"""Connects a URL rule. Works exactly like the :meth:`route`
decorator but does not register the view function for the endpoint. Basically this example:: @app.route('/')
def index():
pass Is equivalent to the following:: def index():
pass
app.add_url_rule('index', '/')
app.view_functions['index'] = index :param rule: the URL rule as string
:param endpoint: the endpoint for the registered URL rule. Flask
itself assumes the name of the view function as
endpoint
:param options: the options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object
"""
options['endpoint'] = endpoint
options.setdefault('methods', ('GET',))
self.url_map.add(Rule(rule, **options))
注释也不过多解释
它的主要工作就是将route的rule和endpoint建立关系。通过 url_map.add(Rule(rule, **options)) 方法。
2.3 url_map
实际上是flask的和核心库 werkzeug 自己定义的一个存储url路径的‘仓库’,
werkzeug 最核心的路由功能:添加路由规则(也可以使用 m.add),把路由表绑定到特定的环境(m.bind),匹配url(urls.match)。正常情况下返回对应的 endpoint 名字和参数字典,可能报重定向或者 404 异常。
其实是 url 到 endpoint 的转换:通过 url 找到处理该 url 的 endpoint。至于 endpoint 和 view function 之间的匹配关系,werkzeug 是不管的。
2.4 dispatch_request
def dispatch_request(self):
"""Does the request dispatching. Matches the URL and returns the
return value of the view or error handler. This does not have to
be a response object. In order to convert the return value to a
proper response object, call :func:`make_response`.
""" req = _request_ctx_stack.top.request
if req.routing_exception is not None:
self.raise_routing_exception(req)
rule = req.url_rule # dispatch to the handler for that endpoint
return self.view_functions[rule.endpoint](**req.view_args)
这个方法做的事情就是找到请求对象 request,获取它的 endpoint,然后从 view_functions 找到对应 endpoint 的 view_func ,把请求参数传递过去,进行处理并返回。
补 flask路由规则
- 通过 @app.route 或者 app.add_url_rule 注册应用 url 对应的处理函数
- 每次请求过来的时候,会事先调用路由匹配的逻辑,把路由结果保存起来
- dispatch_request 根据保存的路由结果,调用对应的视图函数
最后分享来自segementfault的_Zhao的 文章, 他的路由思想和我理解的想法差不多。
----补 2017/2/22----
介绍一个搭建RESTful API 之 实现WSGI服务的URL映射,也是类似于router源代码的介绍,说的很不错。
flask源码分析的更多相关文章
- Flask源码分析二:路由内部实现原理
前言 Flask是目前为止我最喜欢的一个Python Web框架了,为了更好的掌握其内部实现机制,这两天准备学习下Flask的源码,将由浅入深跟大家分享下,其中Flask版本为1.1.1. 上次了解了 ...
- Flask源码分析一:服务启动
前言: Flask是目前为止我最喜欢的一个Python Web框架了,为了更好的掌握其内部实现机制,这两天准备学习下Flask的源码,将由浅入深跟大家分享下,其中Flask版本为1.1.1. Flas ...
- 【Flask源码分析——请求上下文与应用上下文】
Flask中有两种上下文,请求上下文和应用上下文.两者的作用域都处于一个请求的局部中. 查看源代码,上下文类在flask.ctx模块中定义 AppContext类定义应用上下文,app是当前应用Web ...
- Flask源码剖析详解
1. 前言 本文将基于flask 0.1版本(git checkout 8605cc3)来分析flask的实现,试图理清flask中的一些概念,加深读者对flask的理解,提高对flask的认识.从而 ...
- Flask系列10-- Flask请求上下文源码分析
总览 一.基础准备. 1. local类 对于一个类,实例化得到它的对象后,如果开启多个线程对它的属性进行操作,会发现数据时不安全的 import time from threading import ...
- Flask系列之源码分析(一)
目录: 涉及知识点 Flask框架原理 简单示例 路由系统原理源码分析 请求流程简单源码分析 响应流程简单源码分析 session简单源码分析 涉及知识点 1.装饰器 闭包思想 def wapper( ...
- flask框架(三)——路由系统route转换成add_url_rule及源码分析
这节我们不用@app.route来写路由,而是通过add_url_rule 传统写法 (<int:nid>传递int类型参数,endpoint是取别名) @app.route('/det ...
- flask/app.py-add_url_rule源码分析
之前分析route方法的时候,可以看到中间会调用add_url_rule方法,add_url_rule方法和route方法一样属于Flask这个类的. add_url_rule方法主要用来连接url规 ...
- Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析
Flask框架(三)—— 请求扩展.中间件.蓝图.session源码分析 目录 请求扩展.中间件.蓝图.session源码分析 一.请求扩展 1.before_request 2.after_requ ...
随机推荐
- [LeetCode] Factor Combinations 因子组合
Numbers can be regarded as product of its factors. For example, 8 = 2 x 2 x 2; = 2 x 4. Write a func ...
- 基于centos的lnmp搭建
部署lnmp环境 安装配置mariadb配置php配置phpmyadmin配置php-fpm配置nginx配置测试 LNMP(linux,nginx,mariadb,php)部署,以下默认在root权 ...
- NC6开发配置流程
1.功能注册 2.菜单注册 3.单据类型管理 4.单据模板初始化 5.查询模板初始化 6.功能节点默认模板设置 7.编码对象注册.编码规则定义
- ftp文件的部署
之前在公司搭建了一个静态资源服务器,现在来记录一下 我们是通过搭建vsftp服务,然后结合apache.访问方式为http的方式 一:VSFTPD环境安装 首先我们就是要查看一下vsftpd是否有安装 ...
- 【BZOJ 3993】【SDOI 2015】星际战争
http://www.lydsy.com/JudgeOnline/problem.php?id=3993 调了好长时间啊 这道题设时间为time,那么对于m个武器从S向这m个点连容量为time*Bi的 ...
- Git忽略.gitignore规则不生效的解决办法
在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件). 这个文件每一行保存了一个匹配的规则例如: # 此为 ...
- C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)
一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...
- 利用django创建一个投票网站(三)
创建你的第一个 Django 项目, 第三部分 这一篇从第二部分(zh)结尾的地方继续讲起.我们将继续编写投票应用,并且聚焦于如何创建公用界面--也被称为"视图". 设计哲学 Dj ...
- [DUBBO]Dubbo控制台查看方法
1.dubbo控制台安装方法网上较多,例如转载http://dtbuluo.com/blog/archives/37 2.dubbo控制台查看 由于我们组是开发安装的dubbo.zookeeper等等 ...
- Win7硬盘整数分区一览表
10G=10245 MB 20G=20482 MB 30G=30726 MB 40G=40963 MB 50G=51208 MB 60G=61444 MB 70G=71681 MB 80G=81926 ...