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] Combinations 组合项
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- 学记:spring boot使用官网推荐以外的其他数据源druid
虽然spring boot提供了4种数据源的配置,但是如果要使用其他的数据源怎么办?例如,有人就是喜欢druid可以监控的强大功能,有些人项目的需要使用c3p0,那么,我们就没办法了吗?我们就要编程式 ...
- ubuntu10.04配置XMAPP中的环境变量
1. 显示环境变量:[root@localhost ~]# echo $PATH/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/lo ...
- ZKW线段树
简介 zkw线段树虽然是线段树的另一种写法,但是本质上已经和普通的递归版线段树不一样了,是一种介于树状数组和线段树中间的存在,一些功能上的实现比树状数组多,而且比线段树好写且常数小. 普通线段树采用从 ...
- Python Day19
Django Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Sessio ...
- 在UP Board 上搭建M——L服务器
前言 原创文章,转载引用务必注明链接,水平有限,欢迎指正. 本文环境:ubilinux 3.0 on UP Board 初识免流 所谓免流,就是免除手机访问网络产生的流量费用.其原理在乌云网上有过报道 ...
- Hive : UDFArgumentTypeException Exactly one argument is expected.
Hive执行时Failed.. 分段执行发现排除一些聚合函数或者内置函数后可以正常执行.. 因为Hive-Sql语句比较长..有很多的case when then 排除后发现是聚合函数的用法问题.. ...
- win10 64位专业版系统中显示32位dcom组件配置的方法
word.excel是32位的组件,当用户64位系统在运行窗口中输入dcomcnfg命令时,在打开的组件服务管理窗口,是找不到Microsoft Excel.word程序的.另外,Windows 环境 ...
- WCF学习第二篇:WCF 配置架构。这有助于对wcf配置的理解和记忆
使用 Windows Communication Foundation (WCF) 配置元素,您可以配置 WCF 服务和客户端应用程序. 可以使用配置编辑器工具 (SvcConfigEditor.ex ...