flask 中几种在所有请求之前进行验证的方法之间的差别

在所有请求之前添加钩子

在做验证是否是登陆用户之类的功能时,一定会涉及到与此相关的知识点。

对于直接用 app.add_url_rule() 或者使用 @app.route(...) 的方式来定义路由的情况,我们可以使用@app.before_request() 装饰器来实现在所有请求之前执行某一些验证逻辑代码。

但是对于用blueprint来定义各种路由的方式,blueprint.before_request 不再是一个装饰器,而是一个函数,并且接受一个参数,参数是一个方法名 func。也就是在执行所有请求之前会先执行这个 func 方法

最基本的代码是:

def blueprint_validate_session_in_stock():
    print 'this is [before_request] in blueprint'

def create_app(config_name):
    app=Flask(__name__)
    app.config.from_object(config.config['base'])

    stocks_blueprint.before_request(
        blueprint_validate_session_in_stock)

    app.register_blueprint(main_blueprint)
    app.register_blueprint(stocks_blueprint)

    return app

这样的话,每次访问 stocks_blueprint 模块中的页面,都会打印:this is [before_request] in blueprint

一个有益的对比

由于 blueprint 不仅有 before_request() 方法,还有 before_app_request() 方法,还有 before_app_first_request() 方法,再加上在 app 层面还有 app.before_request() 方法。这四种方法究竟在哪些情况下执行?谁先谁后?这些问题都将直接影响到网站访问控制的逻辑,如果理解错误,还可能造成一些访问的死循环。

我们将前面的代码改为:

#encoding:utf8

from flask import Flask,redirect
import config

from controllers import main_blueprint
from controllers.stocks import stocks_blueprint


def validate_session():
    print 'over the top! this is before_request\n'
def blueprint_validate_app_session_in_stock():
    print '\tthis is [before_app_request] in blueprint\n'
def blueprint_validate_app_session_first_in_stock():
    print '\tthis is [before_app_first_request] in blueprint\n'
def blueprint_validate_session_in_stock():
    print '\tthis is [before_request] in blueprint\n'
    session=None
    if session==None:
        return redirect('/login')

def create_app(config_name):
    app=Flask(__name__)
    app.config.from_object(config.config['base'])

    app.before_request(validate_session)
    stocks_blueprint.before_request(
        blueprint_validate_session_in_stock)
    stocks_blueprint.before_app_first_request(
        blueprint_validate_app_session_first_in_stock
    )
    stocks_blueprint.before_app_request(
        blueprint_validate_app_session_in_stock)

    app.register_blueprint(main_blueprint)
    app.register_blueprint(stocks_blueprint)

    # print app.url_map
    return app

代码的意图是:访问 blueprint_stock 的根页面时,要做 session 验证,如果没有 session 就跳转到 login 页面去

我们首先访问网站根页面,然后点击跳转到 stock 页面,所看到的打印记录是:

# 这是访问网站根页面的反馈

    this is [before_app_first_request] in blueprint

over the top! this is before_request

        this is [before_app_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:45:59] "GET / HTTP/1.1" 200 -

# 这是访问 stock 根页面的反馈

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:46:01] "GET /stocks/ HTTP/1.1" 302 -

# 这是跳转到 login 页面的反馈

over the top! this is before_request

        this is [before_app_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:46:01] "GET /login HTTP/1.1" 200 -

从上面的打印结果来对比,可以得出如下结论:

  • blueprint.before_app_request 会影响全局,即访问网站根页面或其他页面时,它都会生效

  • blueprint.before_app_request 会最先执行,先于 app.before_request

  • blueprint.before_app_first_request 会影响全局,但是只执行一次,适合用在初始化某些变量,它的执行顺序是在 app.before_request 之后

  • blueprint.before_app_request 要慎用,假如上面的代码中将验证 session 不存在就跳转到 login 页面的逻辑代码,写在了 blueprint_validate_app_session_in_stock() 中,就会造成访问的死循环! 因为访问 login 页面时,这个验证的逻辑代码同样会生效:发现没有 session,又一次跳转到 login 页面,造成页面一直在刷新!

关于页面刷新

如果用户停留在某一页面,只是在浏览器上点击了刷新,会有什么效果呢?我们将上面的代码中验证 session 不存在就跳转的 login 页面的代码去掉后,即注释掉这部分代码:

#session=None
#    if session==None:
#        return redirect('/login')

直接访问 blueprint_stock 的根页面来查看一下打印结果:

# 这是第一次访问的打印结果

        this is [before_app_first_request] in blueprint

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:56:25] "GET /stocks/ HTTP/1.1" 200 -

# 这是用户点击刷新后的打印结果:

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:56:48] "GET /stocks/ HTTP/1.1" 200 -

可以看到,刷新后有两个变化:

  • 执行顺序变了,刷新后首先执行的是 app.before_request
  • 刷新后 blueprint.before_app_first_request 不执行了,这个很好理解

结论

  • 一定要慎用 blueprint.before_app_request
  • blueprint 层面没有 before_first_request,如果要使用 blueprint.before_app_first_request 等同于 app.before_first_request 了,这个也要慎用。
  • 对于 blueprint.before_app_first_request 的应用场景是在各个 blueprint 中可以单独添加一些自己需要初始化的变量,各个 blueprint 中的这个操作相互是不会覆盖的,只是在 app 层面的 before_first_request 中做“加操作”,避免了直接修改 app.before_first_request 全局型代码在开发管理层面上带来的不便(假如app层面的代码和各个 blueprint 由不同的人维护)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容