session原理,闪现,请求扩展,中间件,蓝图
session的原理
flask的session源码分析
# 通过app.session_interface()----->可以找到SecureCookieSessionTnterface()类的对象
-open_session:请求来了,从cookie中取出字符串,把字符串反序列化成session对象
def open_session(
self, app: "Flask", request: "Request"
) -> t.Optional[SecureCookieSession]:
s = self.get_signing_serializer(app)
if s is None:
return None
val = request.cookies.get(self.get_cookie_name(app))
if not val:
return self.session_class()
max_age = int(app.permanent_session_lifetime.total_seconds())
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()
-save_session:请求走时,把session对象,序列化成字符串,放到cookie中
def save_session(
self, app: "Flask", session: SessionMixin, response: "Response"
) -> None:
name = self.get_cookie_name(app)
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(app)
httponly = self.get_cookie_httponly(app)
if not session:
if session.modified:
response.delete_cookie(
name,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
httponly=httponly,
)
return
# Add a "Vary: Cookie" header if the session was accessed at all.
if session.accessed:
response.vary.add("Cookie")
if not self.should_set_cookie(app, session):
return
expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore
response.set_cookie(
name,
val, # type: ignore
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
)
闪现
主要作用:假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
-本质其实就是在a页面,把错误信息放到了某个位置,在b页面把错误取出来
放值:
flash(message='信息错误')
分类: flash(message='信息错误',category='error')
取值:get_flashed_messages()
按分类取值: get_flashed_messages(category_filter=['error'])
'''
等同于djagno的message框架
'''
请求扩展
before_request
作用:类比django中间件的peocess_request,在请求到来执行路由函数之前先执行,但是如果有多个,顺序是从上往下执行
应用:基于它做用户登录认证
'''
注意:如果before_request的返回值不是None的情况下,返回的而是别的值,那么后续的请求都不会执行,本次请求直接返回,如果定义了after_request那么会接着它执行, 最终本次请求响应结束。
'''
@app.before_request
def process_request(*args,**kwargs):
if request.path == '/login':
return None
user = session.get('user_info')
if user:
return None
return redirect('/login')
after_request
作用: 类比django中间件中的process_response,如果请求没有出现异常的情况下, 会在请求返回return之前执行. 但是如果有多个顺序是从下往上执行.
@app.after_request # 后执行
def process_response1(response):
print('process_response1 走了')
return response
@app.after_request # 先执行
def process_response2(response):
print('process_response2 走了')
return response
before_first_request
作用:项目启动起来接收到第一次请求时执行
应用:项目初始化用来保证以后项目只要不重启就不再继续执行
@app.before_first_request
def first():
print('我的第一次')
teardown_request
作用: 在每一个路由函数执行完毕之后执行,即使遇到了异常也会执行. (提示: 返回reutrn没有任何的效果, 不能控制返回的结果)
应用: 记录日志
@app.teardown_request
def ter(e): # e就是上一个路由函授执行过程中出现被捕获的异常信息.
print(e)
print('我是teardown_request ')
errorhandler
作用: 绑定错误的状态码进而可以捕获服务器的错误, 并返回对应的错误页面.
@app.errorhandler(500)
def error_500(arg):
return render_template('error.html', message='500错误')
@app.errorhandler(404)
def error_404(arg):
return render_template('error.html', message='404错误')
'''
arg: 错误信息
'''
template_global------全局的标签
作用: 全局的标签, 在任意的html页面中就可以直接使用, 不需要在render_template中传递参数以后才能使用.
@app.template_global()
def sb(a1, a2):
return a1 + a2
# html页面中直接使用, 不需要传递参数.
{{ sb(1,2) }}
template_filter-----过滤器
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
# html页面中直接使用, 不需要传递参数. 其中1传递给a1, 2传递给a2, 3传递给a3. (提示: Django中的过滤器最多只可以传递二个参数)
{{ 1|db(2,3) }}
总结:
1.重点掌握before_request和after_request
2.注意有多个的情况,执行顺序
3.before_request请求拦截后(也就是return了值或者Response对象(jsonify,render_template,redirect))
中间件
class Md(object):
def __init__(self, old_wsgi_app):
self.old_wsgi_app = old_wsgi_app
def __call__(self, environ, start_response):
print('开始之前')
ret = self.old_wsgi_app(environ, start_response)
print('结束之后')
return ret
if __name__ == '__main__':
# 1. 我们发现当执行app.run方法的时候,最终执行run_simple,最后执行app(),也就是在执行app.__call__方法
# 2. 在__call__里面,执行的是self.wsgi_app().那我们希望在执行他本身的wsgi之前做点事情。
# 3. 所以我们先用Md类中__init__,保存之前的wsgi,然后我们用将app.wsgi转化成Md的对象。
# 4. 那执行新的的app.wsgi_app,就是执行Md的__call__方法。
# 5. 最后把原来的wsgi_app替换为自定义的
app.wsgi_app = Md(app.wsgi_app)
app.run()
蓝图
由于项目开发是一个非常耗时间和精力的工程,如果我们将所有的Flask请求方法都写在同一个文件下的话,非常不便于我们代码管理和后期功能代码的添加。
如下示例:我们在一个文件中写入多个路由,这会使代码维护变得困难。
如图所示,如果我们将所有的请求方法写在同一个处理文件下面的话,会导致我们的代码显得很没有逻辑性,如果我们后期想要修改代码或者添加新功能的话,就会显得很突兀,不知道如何下手,此时就需要我们提到的蓝图来解决这个问题,如果学过django可能了解过django中的app,django中app的主要作用就是将django项目分成一个个单独的app模块,然后将所有app分配不同的处理功能,通过路由分配将它们连接成一个大django项目,其实Flask中的蓝图和django中的app功能大同小异,下面我们大概的了解一下Flask的蓝图,代码如下
我们首先创建一个主的路由配置文件manage.py,该文件主要的作用就是启动整个的Flask框架(项目),如图所示
接着,我们在manage.py的平级目录下创建两个文件admin.py 、user.py,我们大概看一下两个文件的内容
这两个文件相当于django中两个app,不同是django中路由分配是将总路由通过include分配给app的urls.py路由文件,而Flask是通过蓝图注册方式将蓝图添加到主app中,user.py,admin.py主要是创建蓝图,然后为创建的蓝图添加路由配置,接着我们就可以在主路由文件manage.py中将我们创建的蓝图注册到主app中。
这样配置好以后就可以实现路由分层管理,我们来试一下,运行主程序manage.py
在浏览器中访问所设置的路由
补充
蓝图还能实现类似django中的路由分发功能,或者叫路由前缀
user.py:
from flask import Blueprint
user = Blueprint('user', __name__, url_prefix='/user/')
'''
url_prefix:路由前缀
'''
@user.route('/user/hello')
def hello():
return '/user/hello'
'''
原来的路由为 http://127.0.0.1:5000/user/hello
现在的路由为 http://127.0.0.1:5000/user/user/hello
在原有路由前加了前缀
'''
本文作者:春游去动物园
本文链接:https://www.cnblogs.com/chunyouqudongwuyuan/p/16566349.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步