目录
django是个大而全的框架,flask是一个轻量级的框架。
django内部为我们提供了非常多的组件:orm/session/cookie/admin/form /modelform/路由/视图/模板/中间件/分页/auth/contenttype/缓存/信号/多数据库连接
flask框架本身没有太多的功能:路由/视图/模板(jinja2)/session/中间件 ,第三方组件非常齐全。
注意:django的请求处理是逐一封装和传递; flask的请求是利用上下文管理来实现的。
before_request/afterequest
route
functools
相同点:都是用于做业务拆分 / 需要注册才能使用 / 都可以在自己内部定义模板和静态文件。
不同点:注册位置不同 、flask before/after_request比django中间件的应用粒度更细 、 django的app内置了很多,flask蓝图没有内置。
相当于是设置了一个全局变量
DBUtils是数据库链接池
wtforms相当于django的form、modelform、SQLAlchemy相当于django的orm
threading.local对象就是为每个线程开辟一块独立的空间来存放数据。
flask没有用,flask自定义Local对象。
将Local对象中的数据维护成一个栈。
{
123:{stack:[]}
}
并暴露:push/pop/top三方法。
- web运行时:栈没用。
- 离线脚本:只有离线脚本时候才可以用。
with app.Context() as ctx:
pass
with app.Context() as ctx:
pass
偏函数就是当函数的参数太多的时候,需要简化,使用(functools.partial)可以创建一个新的函数,这个函数可以固定住原来的参数的部分参数,从而在调用的时候更加的简单
LocalProxy类是一个代理的类,帮助我们去上下文 ctx 和 app_ctx 中去操作数据。
from flask import requset,session,g,current_app
1.创建ctx = RequestContext对象,其内部封装了 Request对象和session数据。
2.创建app_ctx = AppContext对象,其内部封装了App和g。
3.然后ctx.push触发将 ctx 和 app_ctx 分别通过自己的LocalStack对象将其放入到Local中,Local的本质是以线程ID为key,以{“stack”:[]}为value的字典。
4.执行所有的before_request函数
5.执行视图函数
6.执行所有after_request函数(session加密放到cookie中)
7.通过ctx.auto_pop()销毁ctx和app_ctx
1.请求来了
2.生成ctx=里面放了request,和session
3.生成app_ctx=里面放了g,current_app
4.把他俩都放到全局变量中
5.放进session
6.执行before_request
7.执行视图函数
8.执行after_request
9.执行save_session
10.最终,不管是否报异常,都执行auto_pop(从全局变量中把ctx和app_ctx剔除)
默认flask通过一个脚本就可以实现,但由于项目业务可能会比较多,为了方便业务的拆分,我们会创建多个文件(蓝图)进行管理。
放在路由装饰器的下面
1.新的编程思路:
- django、drf数据是通过传递。
- flask,存储在某个地方,以后用的时候去拿。
哪种好?两个不同的实现机制,没有好坏之分。
django好,如果是一个初学者对于django的机制比较好理解,flask学习代价比较大(了解上下文管理机制之后才能更好的理解)。
2.技术点:
- 单例模式的应用场景
- LocalProxy代理类
- 装饰器注意加functools
因为在flask中可以开启多线程的模式,当开启多线程模式进行处理用户请求时,需要将线程之间的数据进行隔离,以防止数据混乱。
Flask自由、灵活,可扩展性强,透明可控,第三方库的选择面广,
开发时可以结合最流行最强大的Python库,
# 依赖jinja2模板引擎
# 依赖werkzurg协议
# blueprint把实现不同功能的module分开.也就是把一个大的App分割成各自实现不同功能的module.
# 在一个blueprint中可以调用另一个blueprint的视图函数, 但要加相应的blueprint名.
# Flask组件
flask-session session放在redis
flask-SQLAlchemy 如django里的ORM操作
flask-migrate 数据库迁移
flask-script 自定义命令
blinker 信号-触发信号
# 第三方组件
Wtforms 快速创建前端标签、文本校验
dbutile 创建数据库连接池
gevnet-websocket 实现websocket
# 自定义Flask组件
自定义auth认证
参考flask-login组件
# a、简单来说,falsk上下文管理可以分为三个阶段:
1、'请求进来时':将请求相关的数据放入上下问管理中
2、'在视图函数中':要去上下文管理中取值
3、'请求响应':要将上下文管理中的数据清除
# b、详细点来说:
1、'请求刚进来':
将request,session封装在RequestContext类中
app,g封装在AppContext类中
并通过LocalStack将requestcontext和appcontext放入Local类中
2、'视图函数中':
通过localproxy--->偏函数--->localstack--->local取值
3、'请求响应时':
先执行save.session()再各自执行pop(),将local中的数据清除
# g是贯穿于一次请求的全局变量,当请求进来将g和current_app封装为一个APPContext类,
# 再通过LocalStack将Appcontext放入Local中,取值时通过偏函数在LocalStack、local中取值;
# 响应时将local中的g数据删除:
RequestContext #封装进来的请求(赋值给ctx)
AppContext #封装app_ctx
LocalStack #将local对象中的数据维护成一个栈(先进后出)
Local #保存请求上下文对象和app上下文对象
# 因为通过维护成列表,可以实现一个栈的数据结构,进栈出栈时只取一个数据,巧妙的简化了问题。
# 还有,在多app应用时,可以实现数据隔离;列表里不会加数据,而是会生成一个新的列表
# local是一个字典,字典里key(stack)是唯一标识,value是一个列表
请求进来时,可以根据URL的不同,交给不同的APP处理。蓝图也可以实现。
#app1 = Flask('app01')
#app2 = Flask('app02')
#@app1.route('/index')
#@app2.route('/index2')
源码中在DispatcherMiddleware类里调用app2.__call__,
原理其实就是URL分割,然后将请求分发给指定的app。
之后app也按单app的流程走。就是从app.__call__走。
gevent-websocket
#快速创建前端标签、文本校验;如django的ModelForm
# flask中的信号blinker
信号主要是让开发者可是在flask请求过程中定制一些行为。
或者说flask在列表里面预留了几个空列表,在里面存东西。
简言之,信号允许某个'发送者'通知'接收者'有事情发生了
@ before_request有返回值,blinker没有返回值
# 10个信号
request_started = _signals.signal('request-started') #请求到来前执行
request_finished = _signals.signal('request-finished') #请求结束后执行
before_render_template = _signals.signal('before-render-template')#模板渲染前执行
template_rendered = _signals.signal('template-rendered')#模板渲染后执行
got_request_exception = _signals.signal('got-request-exception') #请求执行出现异常时执行
request_tearing_down = _signals.signal('request-tearing-down')#请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)
appcontext_pushed = _signals.signal('appcontext-pushed') #请求app上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped') #请求上下文pop时执行
message_flashed = _signals.signal('message-flashed')#调用flask在其中添加数据时,自动触发
原文:https://www.cnblogs.com/saoqiang/p/12527588.html