2.flask中使用装饰器统一验证用户登录
使用注意事项
1.装饰器函数注解要放到离被装饰函数最近的位置。
让请求一进来先执行装饰器,而不是原函数
2.必须使用@functools.wraps(func),否则所有被装饰的函数的名称都变成了inner,函数与url的绑定就重复了,无法识别。
from flask import Flask
import functools
app = Flask(__name__)
def auth(func):
@functools.wraps(func)
def inner(*args, **kwargs):
func(*args, **kwargs)
return inner
@app.route("/login")
@auth
def login():
pass
if __name__ == '__main__':
app.run()
对上一篇中用户登录验证功能采用装饰器进行优化
from flask import Flask, render_template, request, redirect, url_for, session
import functools
app = Flask(__name__, template_folder="templates")
# 使用session时需要,值可以先随便写一个
app.secret_key = "12345"
# 定义一个全局变量来当做数据库
DATA_DICT = {
1: {'name': '张三', 'age': 18, 'gender': '男'},
2: {'name': '李四', 'age': 22, 'gender': '男'}
}
def auth(func):
"""
使用装饰器验证用户是否登录
:param func:
:return:
"""
@functools.wraps(func)
def inner(*args, **kwargs):
username = session.get('xx')
if not username:
# 如果未登录则跳转到登录页面
return redirect("/login")
return func(*args, **kwargs)
return inner
@app.route("/login", methods=["GET", "POST"])
def login():
method = request.method
if method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
if username == 'admin' and password == '123':
session['xx'] = username
return redirect("/index")
error = '用户名密码错误'
return render_template("login.html", error=error)
# endpoint给路由取了个别名,如果不指定,endpoint的默认值为函数名
# endpoint的值不能重名
@app.route("/index", endpoint="index_page")
@auth
def index():
return render_template("index.html", DATA_DICT=DATA_DICT)
@app.route("/edit", methods=['GET', "POST"])
@auth
def edit():
id = request.args.get('nid')
id = int(id)
if request.method == 'POST':
name = request.form.get('name')
age = request.form.get('age')
gender = request.form.get('gender')
DATA_DICT[id]['name'] = name
DATA_DICT[id]['age'] = age
DATA_DICT[id]['gender'] = gender
return redirect(url_for("index_page"))
info = DATA_DICT[id]
return render_template("edit.html", info=info)
# 默认就是str类型,可以不写
@app.route("/del/<int:nid>")
@auth
def delete(nid):
print(f"nid={nid}")
# 根据key删除dict的元素
del DATA_DICT[nid]
# 通过url_for来重定向跳转
return redirect("/index")
if __name__ == '__main__':
app.run()
注意:
1.@auth一定要放在@app.route(“url”)下面,因为url要跟装饰函数建立关系。
2.装饰函数一定要使用@functools.wraps(func),保证每个函数的__name__是它自己的,而不是统一的inner,防止出现如下错误:
AssertionError: View function mapping is overwriting an existing endpoint function: inner