什么叫钩子函数呢?其实就是一个特殊的装饰器,用于某些 业务场景的前置操作和后置操作。
Flask 钩子函数
什么是 钩子函数?
钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。一段用以处理系统消息的程序。“钩子”就是在某个阶段给你一个做某些处理的机会。
钩子函数: 1、是个函数,在系统消息触发时被系统调用 2、不是用户自己触发的。
Flask 钩子函数
执行顺序
钩子函数使用
可以直接用在app 上, 也可以用在蓝图上
钩子函数作用在蓝图上
import os
from flask import Blueprint, request, render_template, redirect, url_for, jsonify, Response, session, g
from sqlalchemy import or_, and_, not_
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from ext import db
from settings import Config
from .modle import User
import hashlib
user_bp = Blueprint('user', __name__)
# 需要鉴权的路径
required_login_list = ["/user/center", '/user/change']
# 允许上传的图片格式
allow_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp']
@user_bp.route("/")
def base():
return render_template('base.html')
@user_bp.before_app_first_request
def first_request():
print("首次进这个蓝图")
# 重点
@user_bp.before_app_request
def first():
print("蓝图里,所有的路由执行之前都会执行这里,可以用做鉴权")
if request.path in required_login_list:
uid = session.get('uid')
if not uid:
print("鉴权失败")
# 重定向前面要有return 代表返回结束,不然就没有作用了
return redirect(url_for('user.login'))
else:
print("鉴权成功")
user = User.query.get(uid)
g.user = user
@user_bp.after_app_request
def after_request_test(response):
# response.set_cookie('a', 'bbbb', max_age=19)
print('如果没有未处理的异常抛出,在每次请求结束运行')
return response
@user_bp.teardown_app_request
def teardown_request_test(response):
print('在每次请求后运行, 即使有未处理的异常抛出也执行')
return response
@user_bp.route('/user/register', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template('user/register.html')
else:
username = request.form.get("username")
password = request.form.get('password')
# 进行md5 加密
# password = hashlib.md5(password.encode('utf-8')).hexdigest()
password = generate_password_hash(password)
phone = request.form.get('phone')
email = request.form.get('email')
user = User()
user.username = username
user.password = password
user.email = email
user.phone = phone
db.session.add(user)
db.session.commit()
return redirect(url_for("user.base"))
# 用于做手机号码的唯一性校验,通过阿贾克斯方式
@user_bp.route('/user/check_phone')
def check_phone_exists():
phone = request.args.get('phone')
user = User.query.filter(User.phone == phone).all()
print("--------------------")
print(user)
# code: 400 不能用 200 可以用
if len(user) > 0:
return jsonify(code=400, msg='此号码已被注册')
else:
# print("看看这里进来了没有")
return jsonify(code=200, msg='此号码可用')
@user_bp.route('/user/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('user/login.html')
else:
phone_num = request.form.get('phone')
pwd = (request.form.get('password'))
# print("--------看看原始密码-------------" + request.form.get('password'))
user = User.query.filter(and_(User.isDelete == 0, User.phone == phone_num)).first()
if user:
flag = check_password_hash(user.password, pwd)
if flag:
# 通过 cookie 来记录登陆信息
# 使用重定向就不能传递参数回去
# response = redirect(url_for('user.base'))
# 这样也是错误的, 返回的是一个str 对象
# response = render_template('base.html', user=user)
response = Response(render_template('user/index.html', user=user))
# response.set_cookie('uid', str(user.id), max_age=1800)
# 通过 sessionId来记录登陆信息
session['uid'] = user.id
print("看看session id " + str(session['uid']))
return response
else:
return render_template('user/login.html', msg='用户名或者密码错误')
else:
return render_template('user/login.html', msg='用户未注册')
@user_bp.route('/user/logout')
def logout():
response = Response(render_template('user/login.html'))
# response.delete_cookie('uid')
del session['uid']
print("删除了session id")
return response
@user_bp.route('/user/center', methods=['GET', 'POST'])
def center():
# g 是全局变量
return render_template('user/center.html', user=g.user)
运行效果
应用场景
可以看出, 就是一个装饰器, 可以用来做登陆的鉴权, 异常发生后也可以进行处理。