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 ...
随机推荐
- bzoj1036 [ZJOI2008]树的统计Count(树链剖分)
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
- 为什么有时候访问某些加密https网站是不需要证书的? https? ssl?
根证书是CA颁发给自己的证书, 是信任链的起点 1.所有访问https的网站都是需要证书的. 2.对于某些网站,尤其是证书颁发机构的网站,操作系统自动添加了这些网站访问需要的证书到证书管理器中,所以就 ...
- java递归方法求数组最大元素
一直对递归写法不是很熟悉,特写一个增进理解 /** * Created by Administrator on 2017-11-01. */ public class recursion { priv ...
- 【hdu3555】 Bomb
http://acm.hdu.edu.cn/showproblem.php?pid=3555 (题目链接) 题意 求区间${[1,n]}$含有49的数的个数. Solution 数位dp,先求出不含4 ...
- CentOS7搭建elasticsearch集群
准备三个节点,系统版本为CentOS7.3. 11.0.10.18 es01 11.0.10.19 es02 11.0.10.20 es03 1.安装java环境 # yum install -y j ...
- phpredis -- Redis Arrays用法
Redis Arrays 来自地址:https://github.com/phpredis/phpredis/blob/master/arrays.markdown#readme 扩展原文件array ...
- [opencv] 图像几何变换:旋转,缩放,斜切
几何变换 几何变换可以看成图像中物体(或像素)空间位置改变,或者说是像素的移动. 几何运算需要空间变换和灰度级差值两个步骤的算法,像素通过变换映射到新的坐标位置,新的位置可能是在几个像素之间,即不一定 ...
- web项目中日志管理工具的使用
在web项目中,很多时候会用到日志管理工具,常见的日志管理用具有:JDK logging(配置文件:logging.properties) 和log4j(配置文件:log4j.properties) ...
- 科学计算三维可视化---Traits属性的监听
Traits属性的监听 HasTraits对象所有Traits属性都自动支持监听功能,当每个Traits属性发生变化时,HasTraits对象会通知监听此属性的函数 两种监听模式 静态监听 动态监听 ...
- Kafka 0.8 Consumer处理逻辑
0.前言 客户端用法: kafka.javaapi.consumer.ConsumerConnector consumer = kafka.consumer.Consumer.createJavaCo ...