flask基础之app初始化(四)
前言
flask的核心对象是Flask,它定义了flask框架对于http请求的整个处理逻辑。随着服务器被启动,app被创建并初始化,那么具体的过程是这样的呢?
系列文章
一个最基本web应用的flask代码
from flask import Flask
import os
# 创建app对象
app = Flask(__name__,template_folder='static/html')
# 加载配置文件
app.config['SECRET_KEY'] = '123'
# 加载蓝图
app.register_blueprint(rest, url_prefix='')
# 加载请求钩子
@rest.before_request
def rest_test():
print('this is a test')
pass
# 定义api处理视图
@app.route('/test1')
def test():
return 'OK'
@定义错误处理逻辑
@app.errorhandler(400)
def handle_errer(errer):
print(errer)
return errer
if __name__ == '__main__':
app.run(host='127.0.0.1', port=80, debug=True)
如上所示,一个完整的web应用所拥有的最基本的东西就这些了,我们一步步分析。
第一步:创建Flask对象
创建一个Flask的app对象作为备用是一切的开端,看一下初始化干了什么?
class Flask(_PackageBoundObject):
request_class = Request # 指定请求对象
response_class = Response # 指定响应对象
jinja_environment = Environment # 指定前端模板语言环境
app_ctx_globals_class = _AppCtxGlobals # 设置app全局对象,本质是一个字典
request_globals_class = property(_get_request_globals_class, # 设置请求上下文全局对象,其等于app_ctx_globals_class
_set_request_globals_class)
config_class = Config # 设置参数配置对象
debug = ConfigAttribute('DEBUG') # 配置文件中如果DEBUG=True就启用debug模式
testing = ConfigAttribute('TESTING') # 配置文件中如果TESTING=True就启用TESTING模式
secret_key = ConfigAttribute('SECRET_KEY') # 配置文件中如果SECRET_KEY=‘xx’就启用了密匙,默认是不启用的
# 配置文件中如果SESSION_COOKIE_NAME=‘xx’就启用了在cookie中session信息的名字,默认是session
session_cookie_name = ConfigAttribute('SESSION_COOKIE_NAME')
# 配置文件中如果PERMANENT_SESSION_LIFETIM=‘xx’就启用了session信息的失效时间,默认是31天,即一个月
permanent_session_lifetime = ConfigAttribute('PERMANENT_SESSION_LIFETIME',
get_converter=_make_timedelta)
# 设置发送文件功能最大的缓存超时时间,默认为12小时
send_file_max_age_default = ConfigAttribute('SEND_FILE_MAX_AGE_DEFAULT',
get_converter=_make_timedelta)
# 通过LOGGER_NAME指定日志对象的名称
logger_name = ConfigAttribute('LOGGER_NAME')
# 启用json格式的编解码
json_encoder = json.JSONEncoder
json_decoder = json.JSONDecoder
# 设置默认jinja模板环境
jinja_options = ImmutableDict(
extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
)
# 常用默认的配置集合
default_config = ImmutableDict({
'DEBUG': get_debug_flag(default=False), # 默认不开启DEBUG模式
'TESTING': False, # 默认不开启TESTING模式
'SECRET_KEY': None, # 默认没有密匙
'PERMANENT_SESSION_LIFETIME': timedelta(days=31), # 默认session失效时间一个月
'USE_X_SENDFILE': False, # 不启用X_SENDFILE功能
'LOGGER_NAME': None, # 不指定logger名字,使用的是__name__
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None, # 设置服务器的名字,默认None
'SESSION_COOKIE_NAME': 'session', # 设置cookie中的session名字
'MAX_CONTENT_LENGTH': None, # 限制提交请求的最大字节数
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12), # 设置文件最大缓存时间
'PREFERRED_URL_SCHEME': 'http', # 默认的通讯协议
'JSONIFY_MIMETYPE': 'application/json', # 当json数据交互时,设置响应头的mimetype参数
})
url_rule_class = Rule # 指定路由对象管理路由
session_interface = SecureCookieSessionInterface() # 指定session会话对象
def __init__(self,
import_name, # 指定app的名字
static_path=None, # 会赋值给static_url_path参数,所以一般设置static_url_path而不是这个
static_url_path=None, # 设置静态文件路由的前缀,默认为“/static”,即static_folder的路径
static_folder='static', # 指定静态文件是哪个目录
template_folder='templates',# 模板文件的存放目录,默认值为"templates"
instance_path=None, # 设置配置文件的路径,在instance_relative_config=True情况下生效
instance_relative_config=False, # 设置为True表示配置文件相对于实例路径而不是根路径
root_path=None): # app所在的根路径,默认指的是创建app这个代码的文件的目录。
# 所有定义的视图函数存放字典,以视图函数的标识符为键,视图函数对象为字典;
self.view_functions = {}
# 所有自定义的错误处理方法的存放字典,以蓝图名字为键
self.error_handler_spec = {None: self._error_handlers}
# 所有的与url错误处理方法存放列表
self.url_build_error_handlers = []
# 所有的http请求处理前的请求钩子方法存放字典
self.before_request_funcs = {}
# 第一次请求处理前的请求钩子方法存放字典
self.before_first_request_funcs = []
# 所有的http请求处理后的请求钩子方法存放字典
self.after_request_funcs = {}
# 在处理即使存在异常的情况下的请求处理后的请求钩子方法存放字典
self.teardown_request_funcs = {}
# 应用上下文被弹出之前的处理函数存放点
self.teardown_appcontext_funcs = []
# url_value_preprocessor装饰器添加,URL路径预提取
self.url_value_preprocessors = {}
# url_defaults装饰器回调添加的,在生成url时设置规则参数默认值
self.url_default_functions = {}
self.blueprints = {} # 所有的蓝图的保存字典
self.extensions = {} # 所有的flask的扩展对象的存放字典
self.url_map = Map() # 所有的Rule对象保存的字典
# 添加访问静态文件的Rule对象
if self.has_static_folder:
self.add_url_rule(self.static_url_path + '/<path:filename>',
endpoint='static',
view_func=self.send_static_file)
初始化传入相关的参数后,会执行上述代码生成一个app对象。
第二步:加载配置文件
加载配置文件有多种方式,现在只说例子中的情况:
app.config['SECRET_KEY'] = '123'
app的config对象其实是Config实例,是一个dict类型的子类,也就是说app的配置是通过一个字典来保存的,新加载的配置如果键和原来默认的配置的键相同将更新,否则添加。
class Config(dict):
pass
详细的参数配置方式参考: flask之安装和使用入门
第三步:加载蓝图
app的register_blueprint方法就是用来加载蓝图的。
app.register_blueprint(rest, url_prefix='')
# 源码
def register_blueprint(self, blueprint, **options):
......
self.blueprints[blueprint.name] = blueprint
self._blueprint_order.append(blueprint)
blueprint.register(self, options, first_registration)
如上,在app的blueprints和_blueprint_order属性中添加蓝图对象,同时蓝图调用register方法初始化。
第四步:加载请求钩子
请求钩子常用的有五种,它们通过装饰器的方式添加到app相应的存储字典中。
before_first_request:在处理第一个请求前运行。
before_request:在每次请求前运行。
after_request:如果没有未处理的异常抛出,在每次请求后运行。
teardown_request:在每次请求后运行,即使有未处理的异常抛出。
teardown_appcontext:在每次请求结束后应用上下文被弹出时执行,即appcontext调用pop方法;
@app.before_request
def test():
pass
第五步:加载视图函数
app通过route装饰器加载视图函数,将标识符和视图函数作为键值对加入app的view_functions字典属性中。
@app.route('/test3', endpoint='mytest')
def test3():
return 'ok'
route装饰器调用了app.add_url_rule(rule, endpoint, f, **options)方法,主要源码步骤为:
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
...
rule = self.url_rule_class(rule, methods=methods, **options) # 创建一个Rule对象
。。。
self.url_map.add(rule) # 在app的url_map属性即Map对象中加入rule对象
。。。
self.view_functions[endpoint] = view_func # 在app的view_functions属性中加入标识符和视图函数的键值对
第六步:加载错误处理方法
app通过errorhandler装饰器加载对应的错误或状态码相应的处理方法。
@app.errorhandler(400)
def handle_errer(errer):
print(errer)
return errer
# 其主要源码
def _register_error_handler(self, key, code_or_exception, f):
# 可以传入状态码或我们自定义的异常
exc_class, code = self._get_exc_class_and_code(code_or_exception)
handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {})
handlers[exc_class] = f
总结
flask框架的核心对象有:
Flask,AppContext,Map, RequestContext,Request,Response,Rule,Blueprint,session,_AppCtxGlobals;Flask主要管理着AppContext,RequestContext,以及所有的请求的处理步骤;
AppContext为应用上下文对象,主要管理app对象的获取和请求的临时状态存储变量g;
RequestContext为请求上下文,主要管理Request对象和保存会话的session对象;
Request为请求对象,在发生请求是随着RequestContext被创建而创建,管理着请求数据和Rule对象;
Response为响应对象,在应用逻辑处理完毕后创建,管理着响应数据和响应方法;
Rule路由对象,管理着路由和视图处理函数的标识符的对应关系;
Map对象管理着所有的标识符和其视图函数对象的一一对应关系;
Blueprint对象,Flask对象的缩小版,主要是为了对大量的视图函数做分类管理;
session为保存会话信息的容器,可以看做一个字典;
_AppCtxGlobals即g变量,用来在每次请求中临时存储资源,它属于应用上下文的一个属性。
参考:
flask基础之app初始化(四)的更多相关文章
- flask基础之AppContext应用上下文和RequestContext请求上下文(六)
前言 应用上下文和请求上下文存在的目的,官方文档讲的很清楚,可参考: http://www.pythondoc.com/flask/appcontext.html 应用上下文对象在没有请求的时候是可以 ...
- flask基础之请求处理核心机制(五)
前言 总结一下flask框架的请求处理流程. 系列文章 flask基础之安装和使用入门(一) flask基础之jijia2模板使用基础(二) flask基础之jijia2模板语言进阶(三) flask ...
- 【视频】零基础学Android开发:蓝牙聊天室APP(四)
零基础学Android开发:蓝牙聊天室APP第四讲 4.1 ListView控件的使用 4.2 BaseAdapter具体解释 4.3 ListView分布与滚动事件 4.4 ListView事件监听 ...
- Flask 基础组件(四):模板
1.模板的使用 1.1 语法 1.1.1 流程控制 逻辑语法 Jinja2模板语言中的 for {% for foo in g %} {% endfor %} Jinja2模板语言中的 if {% ...
- Flask基础全套
Flask简介 Flask是主流PythonWeb三大框架之一,其特点是短小精悍以及功能强大从而获得众多Pythoner的追捧,相比于Django它更加简单更易上手,Flask拥有非常强大的三方库,提 ...
- 狗书无敌,天下第一(flask基础)
为什么选择使用flask? 和其他框架相比, Flask 之所以能脱颖而出,原因在于它让开发者做主,使其能对程序具有全面的创意控制. 在 Flask 中,你可以自主选择程序的组件,如果找不到合适的,还 ...
- flask基础三
一.路由和视图(基础二上补充) (1)有参装饰器 路由采用的是有参装饰器实现的 @app.route("/index",methods=["GET"," ...
- flask基础入门
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...
- flask框架----flask基础
知识点回顾 1.flask依赖wsgi,实现wsgi的模块:wsgiref,werkzeug,uwsgi 2.实例化Flask对象,里面是有参数的 app = Flask(__name__,templ ...
随机推荐
- git 常用命令(含删除文件)
git 常用命令(含删除文件) Git常用操作命令收集: 1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git 查看远程仓库: ...
- 转载manifold learning一篇
我恨自己不干活儿,不过也没辙. 早晚要学习流形的,今天先转一篇文章,以后找不到就尿了. 我真羡慕数学系的人,╮(╯▽╰)╭. 发信人: Kordan (K&M), 信区: AI标 题: do ...
- [洛谷P5081]Tweetuzki 爱取球
题目大意:有$n$个球,每一次取一个球然后放回,问期望多少次取遍所有球 题解:令$f_i$表示已经取了$i$种球,还要取的次数的期望.$f_i=\dfrac in(f_i+1)+\dfrac{n-i} ...
- BZOJ 3881: [Coci2015]Divljak
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 553 Solved: 176[Submit][Sta ...
- HTML的标签元素分类的区别
HTML ,即Hyper Text Markup Language 超文本标记语言: 文本:纯字符,如window中的txt文本 超文本:在纯文本中嵌入样式,图片,音频,视频,链接等内容 HTML的基 ...
- CAS使用心得
1.理解CAS实现SSO需要哪些组成部分 2.理解CAS实现SSO流程,包括登陆.注销.二次登陆.其他应用登陆 3.CAS部署需要SSL支持,理解容器如何开启SSL.服务端证书.jre证书信任.创建以 ...
- Android 资源目录 相关知识 raw、 drawable、 values..
一定要看的 Android 资源目录的相关知识 raw drwable valueshttp://blog.csdn.net/shichexixi/article/details/5985677 ht ...
- 解题:CF949D Curfew
题面 整体的思路就是在均摊每个宿舍的人数,注意一个人可以跑好几次=.= 可以发现多的学生往中间跑一定能跑过宿管,所以只考虑学生们能不能及时跑到人不够的宿舍.对两边记录两个已经满足要求的宿舍,然后用前/ ...
- Redis学习基础一
今天开始系统的学习redis基础知识,以往只是看redis的手册,貌似总是记不住.这次尝试手记笔记,使得印象更加深刻,从零开始学习.看是很慢,其实很快哟. 一.什么是Redis 至于什么是redis, ...
- svn断开链接后,重新share提交代码报错
前言:svn怎样断开链接并清除干净请查看此地址-->android studio中断开SVN连接,并彻底清理项目中的.svn文件 1.每次把项目重新关联到新的svn地址上,我都抓狂一样的烦躁,因 ...