第十阶段 -- Flask框架05:【Flask高级03:钩子函数】

1. 钩子函数概念

在Flask中钩子函数是使用特定的装饰器装饰的函数。为什么叫做钩子函数呢,是因为钩子函数可以在正常执行的代码中,插入一段自己想要执行的代码。那么这种函数就叫做钩子函数。

在这里插入图片描述

2. 常见的钩子函数

1. before_first_request

处理项目的第一次请求之前执行。

from flask import Flask,request,session,current_app,url_for,g
import os

app = Flask(__name__)

@app.route('/')
def hello_world():
    print("hi")
    return "hello world "

@app.before_first_request
def first_request():
    print('hello world')


if __name__ == '__main__':
    app.run(debug=True)

2. before_request

在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量。请求已经到达了Flask,但是还没有进入到具体的视图函数之前调用。一般这个就是在视图函数之前,我们可以把一些后面需要用到的数据先处理好,方便视图函数使用。

from flask import Flask,request,session,current_app,url_for,g
import os

app = Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)  #加盐  混淆原数据的作用
@app.route('/')
def hello_world():
    print("hi")
    session['uname']="momo"
    return "hello world "

@app.route('/li')
def mylist():
    print("mylist")
    # print("直接取出",g.user)
    if hasattr(g,"user"):
        print("条件取出", g.user)
    return "hello world "

@app.before_request
def before_request():
    # print('在视图函数执行之前执行的钩子函数')
    # 场景:若用户已经登录了,验证时把用户名放入session中,之后取出来,放入钩子函数,以后访问的视图函数中可直接取出来使用
   uname = session.get('uname')
   print(uname)
   if uname:
       g.user = uname

if __name__ == '__main__':
    app.run(debug=True)

3. teardown_appcontext

不管是否有异常,注册的函数都会在每次请求之后执行。

@app.teardown_appcontext
def teardown(exc=None):  
    if exc is None:               
        db.session.commit()
        else: 
            db.session.rollback()
        db.session.remove()
            
4. template filter

在使用Jinja2模板的时候自定义过滤器。

@app.template_filter("upper")
def upper_filter(s):
    return s.upper()

5. context_rocessor

上下文处理器。使用这个钩子函数,必须返回一个字典。这个字典中的值在所有模版中都可以使用。这个钩子函数的函数是,如果一些在很多模版中都要用到的变量,那么就可以使用这个钩子函数来返回,而不用在每个视图函数中的 render_template 中去写,这样可以让代码更加简洁和好维护。

from flask import Flask,request,session,current_app,url_for,g,render_template
import os

app = Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)  # 【加盐】混淆原数据的作用
@app.route('/')
def hello_world():
    print("hi")
    session['uname']="momo"
    # return "hello world "
    return  render_template("index.html")
@app.route('/li')
def mylist():
    print("mylist")
    # print("直接取出",g.user)
    if hasattr(g,"user"):
        print("条件取出", g.user)
    # return "hello world "
    return render_template('list.html')

@app.before_request
def before_request():
    # print('在视图函数执行之前执行的钩子函数')
    # 场景:若用户已经登录了,验证时把用户名放入session中,之后取出来,放入钩子函数,以后访问的视图函数中可直接取出来使用
   uname = session.get('uname')
   print(uname)
   if uname:
       g.user = uname

@app.context_processor
def context_processor():
    if hasattr(g,'user'):
        return {"current_user":g.user}
    else:
        return {}


if __name__ == '__main__':
    app.run(debug=True)

6. errorhandler
  1. errorhandler 接收状态码,可以自定义返回这种状态码的响应的处理方法。在发生一些异常的时候,比如404错误,比如500错误,那么如果想要优雅的处理这些错误,就可以使用 errorhandler 来出来。

  2. 需要注意几点

    * 在 errorhandler 装饰的钩子函数下,记得要返回相应的状态码。

    * 在 errorhandler 装饰的钩子函数中,必须要写一个参数,来接收错误的信息,如果没参数,就会直接报错。

    * 使用flask.abort可以手动的抛出相应的错误,比如开发者在发现参数不正确的时候可以自己手动的抛出一个400错误。

  • 常见的500错误处理:
from flask import Flask,request,session,current_app,url_for,g,render_template,abort
import os

app = Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)  # 【加盐】混淆原数据的作用
@app.route('/')
def hello_world():
    print("hi")
    session['uname']="momo"
    # 500
    print(g.user)
    return render_template("index.html")

@app.errorhandler(500)
def server_error(error):
    return render_template('500.html'),500

if __name__ == '__main__':
    app.run()

  • 常见的404错误处理:
from flask import Flask,request,session,current_app,url_for,g,render_template,abort
import os

app = Flask(__name__)

@app.route('/li')
def mylist():
    print("mylist")
    if hasattr(g,"user"):
        print("条件取出", g.user)
    return render_template('list.html')

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'),404

if __name__ == '__main__':
    app.run()

  • Flask中的abort函数可以手动的抛出相应的错误(如400)
from flask import Flask,request,session,current_app,url_for,g,render_template,abort
import os

app = Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)  # 【加盐】混淆原数据的作用
@app.route('/')
def hello_world():
    print("hi")
    session['uname']="momo"
    return  render_template("index.html")

@app.errorhandler(400)
def args_error(error):
    return '您的参数不正确',400

# 该功能需要先登录才能访问
@app.route('/setting/')
def setting():
    uname = session.get("uname")
    if uname :
        return '欢迎来到设置页面'
    else:
        # 如果没有登录,这时候我就让他跳转到400错误
        abort(400)
    return render_template('list.html')

if __name__ == '__main__':
    app.run()

7. 钩子函数实例
from flask import Flask,session,g,render_template,abort
import os
app = Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)  #加盐  混淆原数据的作用
# @app.route('/')
# def hello_world():
#     print("hello")
#     return 'Hello World!'

# 项目部署好以后,第一次请求之前执行某些特殊
# 01.before_first_request:处理项目的第一次请求之前执行。
# @app.before_first_request
# def first_reuqest():
#     print("我想在第一次请求之前执行")

# 02.before_request:在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量。
# 请求已经到达了Flask,但是还没有进入到具体的视图函数之前调用。一般这个就是在视图函数之前,
# 我们可以把一些后面需要用到的数据先处理好,方便视图函数使用

@app.route('/')
def hello_world():
    print("hi")
    session['uname']="momo"
    # return "hello world "
    # 制作一个错误"500"
    print(g.user)
    return render_template("index.html")

@app.route('/li')
def mylist():
    print("mylist")
    # print("直接取出",g.user)
    if hasattr(g, "user"):
        print("条件取出", g.user)
    # return "hello world "
    return render_template('list.html')

# 场景:若用户已经登录了,验证时把用户名放入session中,之后取出来,放入钩子函数,以后访问的视图函数中可直接取出来使用
@app.before_request
def before_request():
    print('在视图函数执行之前执行的钩子函数')
    uname = session.get('uname')
    print(uname)
    if uname:
        g.user = uname

# 03.context_processor:上下文处理器。使用这个钩子函数,【必须返回一个字典】。
# 这个字典中的值在所有模版中都可以使用。这个钩子函数的函数是,如果一些在很多模版中都要用到的变量,
# 那么就可以使用这个钩子函数来返回,而不用在每个视图函数中的`render_template`中去写,这样可以让代码更加简洁和好维护。
@app.context_processor
def context_processor():
    if hasattr(g,"user"):
        return {"current_user":g.user}
    else:
        return {}

# 04.errorhandler:errorhandler接收状态码,可以自定义返回这种状态码的响应的处理方法。
# 在发生一些异常的时候,比如“404”错误,比如“500”错误,那么如果想要优雅的处理这些错误,就可以使用`errorhandler`来出来
@app.errorhandler(500)
def server_error(error):
     print(error)
     return  render_template("500.html"),500
     # return  render_template("500.html")  #此写法少一个状态码【不推荐】

@app.errorhandler(404)
def request_error(error):
    return  render_template('404.html'),404

@app.errorhandler(400)
def data_error(error):
    return  "您的参数不正确",400

# 该功能需要先登录才能访问
@app.route('/setting/')
def setting():
    uname = session.get("uname")
    if uname :
        return '欢迎来到设置页面'
    else:
        # 如果没有登录,这时候我就让他跳转到400错误
        abort(400)
    return render_template('list.html')

if __name__ == '__main__':
    # app.run(debug=True)
    app.run()

【index.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
     <h2>系统首页</h2>
     <p>当前用户:{{current_user}}</p>
</body>
</html>

【list.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <h2>列表页</h2>
       <p>当前用户:{{current_user}}</p>
</body>
</html>

【500.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <h2> 当前服务器正忙,请稍后再试!!! </h2>
</body>
</html>

【404.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2>您访问的页面进入二次元了!!!!</h2>
</body>
</html>

utils.py

#工具类
# def funa(uname):
#     print('funa  %s' % uname)
#
# def funb(uname):
#     print('funb %s' % uname)
#
# def func(uname):
#     print('func %s' % uname)

from flask import g
def funa():
    print('funa  %s' % g.uname)

def funb():
    print('funb %s' % g.uname)

def func():
    print('func %s' % g.uname)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值