app.py 应用主入口
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠萝测试笔记 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/13 10:31 下午 # file: 8_app.py """ from flask import Flask, views from s8_userview import UserView app = Flask(__name__) app.add_url_rule('/user/', view_func=UserView.as_view('UserView')) app.run(debug=True)
user.html 代码
<html> <body> <h2>name = {{ name }}</h2> <h2>gender = {{ gender }}</h2> </body> </html>
浏览器访问的效果
使用装饰器
在视图函数、视图类中使用装饰器还是一大杀器
检查登录功能
不使用装饰器前的代码
def check_login(): if 用户已经登录: return True else: return False @app.route('/page1', page1) def page1(): if not check_login(): return '请先登录' 执行 page1 的功能 @app.route('/page2', page2) def page2(): if not check_login(): return '请先登录' 执行 page2 的功能
- 在处理 /page1 和 /page2 时需要检查登录,在函数 page1 () 和 page2 () 的头部调用 check_login 函数
- 这种方法虽然实现了功能,但不够简洁
检查登录的装饰器
使用装饰器实现登录的功能,定义检查登录的装饰器 check_login
from flask import request from functools import wraps def check_login(original_function): @wraps(original_function) def decorated_function(*args, **kwargs): user = request.args.get("user") if user and user == "zhangsan": return original_function(*args, **kwargs) else: return "请登录" return decorated_function()
- 装饰器 check_login 本质是一个函数
- 它的输入是一个函数 original_function
- 它的输出也是一个函数 decorated_function
- original_function 是原先的处理 URL 的视图函数,它不包含检查登录的功能逻辑,就是到时候需要添加装饰器的函数
- decorated_function 是在 original_function 的基础上进行功能扩充的函数(这就是装饰器的功能),它首先检查是否已经登录,如果已经登录则调用 original_function,如果没有登录则返回错误
- 使用 functools.wraps (original_function) 保留原始函数 original_function 的属性
在视图函数中使用装饰器
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠萝测试笔记 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/13 10:31 下午 # file: 8_app.py """ from flask import Flask, request from functools import wraps app = Flask(__name__) # 定义装饰器 def check_login(original_function): @wraps(original_function) def decorated_function(*args, **kwargs): user = request.args.get("user") if user and user == "zhangsan": return original_function(*args, **kwargs) else: return "请登录" return decorated_function() @app.route("/page1") @check_login def page1(): return "page1" @app.route("/page2") @check_login def page2(): return "page2" app.run(debug=True)
- page1、page2 两个视图函数更关注请求处理,而检查登录的功能交给装饰器去负责
- 这样,检查登录的功能与 page1 和 page2 本身的功能是分离的
浏览器访问的效果
在视图类中使用装饰器
#!usr/bin/env python # -*- coding:utf-8 _*- """ # author: 小菠萝测试笔记 # blog: https://www.cnblogs.com/poloyy/ # time: 2021/7/13 11:06 下午 # file: 8_viewclass_decorated.py """ from flask import Flask, request, views from functools import wraps app = Flask(__name__) def check_login(original_function): @wraps(original_function) def decorated_function(*args, **kwargs): user = request.args.get("user") if user and user == 'zhangsan': return original_function(*args, **kwargs) else: return '请先登录' return decorated_function class Page1(views.View): decorators = [check_login] def dispatch_request(self): return 'Page1' class Page2(views.View): decorators = [check_login] def dispatch_request(self): return 'Page2' app.add_url_rule(rule='/page1', view_func=Page1.as_view('Page1')) app.add_url_rule(rule='/page2', view_func=Page2.as_view('Page2')) app.run(debug=True)
decorators = [check_login] 设定视图类的装饰器