flask中间件及CBV

flask请求扩展、中间件及CBV与蓝图

1、请求扩展(类似于Django中间件)

1、before_first_request

在项目启动后,接收到的第一个请求,就会执行,before_first_request装饰的函数的执行顺序是谁先注册谁先执行

2、before_request

请求没有经过响应函数的时候就会执行before_request装饰的函数,执行顺序是谁先注册谁先执行,如果被装饰的函数有返回值,后面注册的都不会执行,响应函数也不会执行,但是不会影响after_request执行

3、after_request

在before_request与响应函数执行后执行,必须接受响应参数response,并且要将响应参数response返回,执行顺序是谁先注册后执行

from flask import Flask, request

app = Flask(__name__)

#1执行响应函数之前,相当于django中的process_request
@app.before_request
def before1():
    print('before1')
    # 在before_request中返回后后续before_request与响应函数都不会执行了
    return 'ok'

@app.before_request
def before2():
    print('before2')

#after_request必须接收一个参数,参数为Response对象,而且必须返回
@app.after_request
def after1(response):
    print('after1')
    return response

@app.after_request
def after2(response):
    print('after2')
    return response

# 项目启动后接收到的第一个请求,所要执行的函数,这是整个项目的第一次,
@app.before_first_request
def first():
    print('first')

@app.route('/')
def index():
    print('响应函数')
    return 'ok'


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

4、teardown_request

一旦遇到错误就会执行传递给装饰的函数,没有错误也会执行,但是错误为None,不能处理错误,只能记录错误

5、errorhandle(错误状态码)

可以对错误进行处理,并且做出相应给用户,必须要传错误状态码,只能传一个值

装饰函数可以返回一个值,也可以返回一个html页面

6、template_global()

相当于Django的标签,可以不用在响应函数中传值给html页面,html可以直接使用装饰的函数名

7、template_filter()

django中的过滤器,第一个参数是你要过滤的那个值,可以不用在响应函数返回值中传,页面可以直接使用,要与函数名同名,html中用 | 来划分过滤的第一个元素

from  flask import Flask,request,render_template

app  = Flask(__name__)

@app.teardown_request
def tear(e):
     print(e)
     print("我是teardown_request")

@app.errorhandler(500)
def error_500(e):
    print(e)
    return "我程序崩了,你下次来把"

@app.errorhandler(404)
def error_404(e):
    print(e)
    return render_template("404.html")

#相当于django中的标签。可以不用在响应函数返回值中传,页面可以直接使用要与函数名同名
@app.template_global()
def get_sb(a1,a2):
    return a1 + a2
#在html中的用法:{{get_sb(1,2)}}

#django中的过滤器,第一个参数是你要过滤的那个值,可以不用在响应函数返回值中传,页面可以直接使用,要与函数名同名
@app.template_filter()
def get_something(a1,a2,a3,a4):
    return a1+a2+a3+a4
#在html中的用法:{{1|get_something(2,3,4)}}


@app.route("/")
def index():
    print("我是响应函数")
    return render_template("index.html")


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

2、中间件

flask中的中间件本质是在执行wsgi_app的前后执行的叫做中间件

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'ok'

class MyMiddleware:
    # 继承原来的wsgi_app
    def __init__(self, old_wsgi_app):
        self.old_wsgi_app = old_wsgi_app
    # 重写__call__方法实现中间件
    def __call__(self, environ, start_response):
        print('中间件在before之前的执行')
        ret = self.old_wsgi_app(environ, start_response)
        print('中间件在after之后的执行')
        return ret

if __name__ == '__main__':
    # app.__call__()
    # 源码中推崇这种写法
    app.wsgi_app = MyMiddleware(app.wsgi_app)
    app.run()

3、CBV

路由绑定给类的方式,需要导入views,CBV必须使用路由分发的方式绑定路由,并且路由中要给as_view传参name绑定别名,Index.as_view(name="index")他的作用是返回view对象,我们传递name="index"是给view的__name__改变名字,如果不传,我们没法通过名字来找路由的映射关系,因为都是view

类中设置属性 methods = ["GET"]   #规定哪些请求方式可以请求我这个路由

      decorators =[tt,]   #这个是给我们的响应添加装饰器

1、如果类继承views.View就要用dispatch_request方法

from flask import Flask,views,url_for

app = Flask(__name__)
def tt(func):
   def inner(*args,**kwargs):
       print("你追到我。。")
       rv = func(*args,**kwargs)
       print("嘿嘿嘿。。。")
       return  rv
   return inner

class Index(views.View):
    methods = ["GET"] #规定哪些请求方式可以请求我这个路由
    decorators =[tt,]   #这个是给 我们的响应添加装饰器
    # 如果是views.View就必须是dispatch_request函数
    def dispatch_request(self):
        return "ojbk"
# CBV必须用路由分发,也可以用endpoint做反向解析,endpoint要优先于name=
app.add_url_rule("/index",view_func=Index.as_view(name="index"),endpoint="index1")
# 为什么要给as_view传递name= "index",
#1 as_view再语法就要你传,
#2 他作用Index.as_view(name="index")他返回是的view这个函数对象,我们传递name="index"是给view的__name__改变名字。如果不传,我没有办法通过名字来找路由的映射关系,因为都是”view“

2、如果类继承views.MethodView就是将dispatch_request方法拆分自定义get与post方法

from flask import Flask,views,url_for

app = Flask(__name__)
def tt(func):
   def inner(*args,**kwargs):
       print("你追到我。。")
       rv = func(*args,**kwargs)
       print("嘿嘿嘿。。。")
       return  rv
   return inner

class Login(views.MethodView):
    methods = ["GET","POST"]  # 规定哪些请求方式可以请求我这个路由
    #decorators = [tt, ]  # 这个是给 我们的响应添加装饰器
    # 继承views.MethodView来做路由分发,重写dispatch_request通过请求方法,来找到当前类中的函数
    def get(self):
        print(url_for("index1"))
        return "get"
    def post(self):
        return "post"

app.add_url_rule("/login",view_func=Login.as_view(name="login"))

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

4、蓝图

用来划分目录与指定路由分发,防止循环导入问题

使用:

1、导入蓝图  from flask import Blueprint

2、在视图中注册蓝图  ord = Blueprint("order",__name__)

3、绑定路由用注册的蓝图名绑定路由  @ord.route("/order")

4、在init中注册蓝图  app.register_blueprint(order.ord)

user.py

# 导入蓝图
from flask import Blueprint

# 注册蓝图,user是起的别名,在init中注册的时候找到具体是哪个的蓝图
us = Blueprint('user', __name__)
# 路由使用蓝图对象
@us.route('/user')
def user():
    return 'ok'

__init__.py

from flask import Flask

app = Flask(__name__)

# 导入要执行的函数
from app01 import user
# 注册蓝图
app.register_blueprint(user.us)

给单个蓝图加请求扩展直接在蓝图使用

@blog.before_request

如果给全部的蓝图都加上同一个请求扩展是在app中加

@app.before_request

在init注册的时候可以给蓝图加前缀,访问时需要加上前缀

app.register_blueprint(admin, url_prefix='/admin')
posted @ 2020-04-07 18:32  Mr沈  阅读(338)  评论(0编辑  收藏  举报