装饰器补充:
import functools def auth(func): @functools.wraps(func) # 作用:把原函数的原信息封装到 inner 中 def inner(*args,**kwargs): ret = func(*args,**kwargs) return ret return inner @auth def index(): print("index") # function.__name__ # 获取函数名 print(index.__name__) # 没加 functools.wraps 这个装饰器的时候, index.__name__ 是 "inner";加了 functools.wraps 之后,index.__name__ 就是 "index"
登陆认证:
登陆认证:某些页面只有登陆之后才能访问
# 方式一: # 在需要登陆认证的视图函数中加上以下验证代码: if not session.get("user"): # 获取 session return redirect("/login") # 该方式的缺点:假如需要认证的视图特别多,则需要在每个视图中添加上述代码 # 方式二: # 利用自定义装饰器 def auth(func): def inner(*args,**kwargs): # 先判断是否已经登陆过 if not session.get("user"): # 获取 session return redirect("/login") func(*args,**kwargs) return inner # 然后给需要认证的视图加上上述装饰器 # 方式三: # 利用 before_request 装饰器 @app.before_request def auth(): # 如果是 "/login" 登陆路径,则让其继续走下面的视图函数 if request.path == "/login": # request.path :获取路径 return None if session.get("user"): # 获取 session return None return redirect("/login") # @app.before_request # 装饰器(需要导入)作用:before_request 装饰的函数 在所有视图函数执行之前 都会先被执行;如果遇到了 return xxx,后面的视图函数就不会再走,遇到 return None 则会继续走下面的视图函数(就像是 Django 中间件 process_request 中的 return 一样)
方式二的示例代码:
settings.py
class DevelopmentConfig(object): SECRET_KEY = "vnasioeyh" # session相关(加盐加密)
login_verification.py
from flask import Flask, request, render_template, redirect, session import functools app = Flask(__name__) app.config.from_object("settings.DevelopmentConfig") # 设置配置文件:settings.py 文件中的 DevelopmentConfig 这个类 def auth(func): @functools.wraps( func) # 加上该装饰器的原因:以 index() 为例,经 auth 装饰过的 index函数 是 inner,然后 inner函数和"/index"这个路径绑定, 假如有好多视图函数都加上了这个装饰器,那么 inner 函数就会和好多路径绑定, Flask就不知道你绑定的是哪一个 def inner(*args, **kwargs): # 先判断是否已经登陆过 if not session.get("user"): # 获取 session return redirect("/login") return func(*args, **kwargs) return inner @app.route("/login", methods=["GET", "POST"]) def login(): if request.method == "GET": return render_template("login.html") username = request.form.get("username") password = request.form.get("psw") if username == "neo" and password == "abc123": session["user"] = username # 设置 session return redirect("/index") else: return render_template("login.html", error="用户名密码错误") # 传递参数也可用字典 @app.route("/index") @auth # 登陆认证的装饰器应该写在 app.route() 下面,这样 被 auth() 装饰后的 index() 函数能够作为一个整体(即 inner函数) 再被 app.route() 去装饰,即 被 auth() 装饰的 index() 这个整体,经过 app.route("/index") 装饰后 与 "/index" 这个路径 绑定 def index(): # 登陆之后才能访问 index 页面 return render_template("index.txt") # 模板后缀不影 if __name__ == "__main__": app.run()
# 当好多视图都需要某一个装饰器的时候(如 登陆认证),就可以利用 @app.before_request 来进行相应的逻辑