1. 统一处理
- 需求: 获取用户身份
- 分析: 除了静态资源,基本所有视图都需要获取用户身份,每个视图单独获取出现大量的代码冗余
- 解决办法: 设置 请求钩子,并通过 g变量 将数据传递给视图函数
代码示例
from flask import Flask,session,g app = Flask(__name__) app.secret_key = 'test' # 需求1: 所有视图都需要获取用户身份 # 解决办法: 用钩子函数进行封装 减少代码冗余 @app.before_request def prepare(): 必须使用g变量来传递数据,使用全局变量不能记录并发的多个请求数据 g.name = session.get('username') @app.route(/) index(): if g.name: return "欢迎回来,%s" % g.name else: 首页 @app.route(/demo1/ demo1(): print(g.name) demo1/login login(): """登录""" session['] = zs' 登录成功' if __name__ == __main__: app.run(debug=True)
2. 访问限制
- 需求: 对指定的路由进行访问限制
- 分析: 部分视图需要身份校验,这部分视图每个单独校验仍会出现大量的代码冗余
- 解决办法: 封装 装饰器 完成身份校验逻辑,对指定视图函数设置装饰器
from functools wraps app = Flask() app.secret_key = test @app.before_request prepare(): g.name = session.get() @app.route( g.name @app.route('
需求2: 对部分视图进行访问限制 如个人中心必须登录才能访问 解决方案: 使用装饰器封装访问限制 减少代码冗余 def login_required(f): f = user def wrapper(*args,**kwargs): 获取函数名 print(wrapper.) if g.name: 用户已登录 return f(*args,**kwargs) 正常访问视图函数 else: 用户未登录 abort(401) 400 语法/参数错误 401 未认证 403 已认证,权限不足 404 资源不存在 405 请求方式不支持 500 服务器错误 return wrapper @app.route(/user) @login_required user = login_required(user) user(): 个人中心""" 访问 %s 的个人中心' % g.name : (app.url_map) app.run(debug=True)
functools.wraps
- 系统内置的装饰器,主要用于装饰器中的闭包函数
- 作用是 将被装饰的函数(wrapper)的函数信息 替换为 指定函数(f)的函数信息 (包括name 函数名, doc 函数注释等)
- 未设置wraps装饰器的情况:
def decorater1(f): f = demo kwargs) wrapper @decorater1 demo(): print(哈哈") 调用函数 demo()
运行结果 wrapper 打印闭包函数名 哈哈
- 设置wraps装饰器的情况:
wraps f = demo @wraps(f) 设置装饰器 运行结果 demo 打印原函数名 哈哈
- flask中的函数标记是根据函数名生成的
- 视图函数添加装饰器
login_required
后,函数标记都会使用闭包函数名wrapper
,这样会出现函数标记冲突,程序报错 - 解决办法: 给闭包函数添加装饰器
functools.wraps(f)
,让函数标记使用原视图函数名生成
' 使用装饰器封装访问限制 f = user 会将被装饰的函数(wrapper)的函数信息替换为指定函数(f)的函数信息(__name__ 函数名,__doc__ 函数注释) 设置该装饰器后,可以让闭包函数使用原函数名,避免函数标记出现冲突(函数标记是根据函数名来生成的) kwargs): g.name: kwargs) : abort(401) ) @login_required g.name @app.route(/demo1) @login_required ' (app.url_map) app.run(debug=True)