zoukankan      html  css  js  c++  java
  • flask框架2 请求扩展之类型于django的中间件,请求扩展之错误处理以及标签与过滤器,中间件,cbv写法,蓝图划分目录

    请求扩展之类型于django的中间件

    #flask里面的请求扩展相当于django中的中间件
    from  flask import Flask,request
    
    app  = Flask(__name__)
    
    @app.before_request
    def before1():
        print("我是befor1")
        return "ok"
    
    @app.before_request
    def before2():
        print("我是befor2")
    
    
    @app.after_request
    def after1(response):
        print("响应后的参数",response)
        print("我是after1")
        return response
    
    @app.after_request
    def after2(response):
    
        print("我是after2")
        return response
    
    @app.before_first_request
    def first():
        print("我是第一次")
    
    @app.route("/")
    def index():
        print("我是响应函数")
        return "ok"
    
    if __name__ == '__main__':
    
        app.run()

    总结(执行顺序按下面的编号)

    1 before_first_request 当项目启动后,接收到的第一个请求,就会执行before_first_request装饰的函数,执行顺序也是谁先注册就谁先执行,无论有没有返回值,后面都会执行
    
    2 before_request 请求没有经过响应函数的时候,会执行before_request装饰的函数,谁先注册谁先执行。只要有一个函数有返回值,后面的所有before_request都不会执行,且响应函数也不会执行。其有没有返回值都不会影响after_request的执行
    
    3 after_request是再before_request与响应函数执行后执行。他必须接收响应参数,并且要把响应返回。执行顺序是谁先注册后执行。

    请求扩展之错误处理以及标签与过滤器

    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|4,2,3}}
    
    
    @app.route("/")
    def index():
    
        print("我是响应函数")
        return render_template("index.html")
    
    
    if __name__ == '__main__':
    
        app.run()

    总结

    1 teardown_request,一旦遇到错误就会执行,并且把错误传递给teardown_request装饰的函数, 没有错误也会执行,但是是错误为None,他并不能处理错误,只能记录
    2 errorhandle 可以捕获错误,并且对错误做出响应,返回给用户,如果你要用errorhandler你必须指定他捕获哪种类型的错误,就必须传错误码,然后就返回值,返回给用户

    中间件(了解的知识点)

    ##了解的知识点
    
    from flask import Flask
    
    app = Flask(__name__)
    class MyMiddleware:
        def __init__(self,old_wsgi_app):
            self.old_wsgi_app =old_wsgi_app
        def __call__(self, environ, start_response):
            #这befor的befor
            print("开始之前")
            ret = self.old_wsgi_app(environ, start_response)
            #这是after的after
            print("结束之后")
            return ret
    
    @app.route("/")
    def index():
        return "ok"
    
    
    if __name__ == '__main__':
        app.wsgi_app = MyMiddleware(app.wsgi_app)
        app.run()

    cbv写法

    基础版

    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,]   #这个是给 我们的响应添加装饰器
        def dispatch_request(self):
            return "ojbk"
    
    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“

    常用版

    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, ]  # 这个是给 我们的响应添加装饰器
        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"))
    #实现方法是重写了dispatch_request,通过请求方法,来找到当前类中的函数。
    
    if __name__ == '__main__':
        app.run()

    蓝图划分目录

    初版不用蓝图划分,可以运行flask,但可能有交叉导入问题

    # app01/__init__.py
    from flask import Flask
    app = Flask(__name__)
    
    from app01 import user    # 导入路由
    
    # app01/user.py
    from app01 import app
    
    @app.route('/user')
    def user():
        return 'user'
    
    # manage.py
    from app01 import app
    
    if __name__ == '__main__':
        app.run()

    使用蓝图,避免交叉导入问题

    # app01/__init__.py
    from flask import Flask
    app = Flask(__name__)
    
    from app01 import user
    from app01 import order
    app.register_blueprint(user.us)     # 注册蓝图
    app.register_blueprint(order.ord)
    
    # app01/order.py
    from flask import Blueprint
    ord = Blueprint('/order',__name__)
    
    @ord.route('/order')
    def order():
        return 'order'
    
    # app01/user.py
    from flask import Blueprint
    
    us = Blueprint('/user',__name__)
    
    @us.route('/user')
    def user():
        return 'user'
    
    # manage.py
    from app01 import app
    
    if __name__ == '__main__':
        app.run()

    简单应用程序目录示例

    # run.py
    from pro_flask import app
    
    if __name__ == '__main__':
        app.run()
        
    # pro_flask/__init__.py
    from flask import Flask
    
    app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static')
    
    from .views.account import account
    from .views.blog import blog
    from .views.user import user
    
    @app.before_request     # 所有app都执行
    def befor1():
        print("我是app的beforrequest")
    
    app.register_blueprint(account)
    app.register_blueprint(blog)
    app.register_blueprint(user)
    
    # pro_flask/views/user.py
    from flask import Blueprint
    
    user = Blueprint('us',__name__) #us为名称空间
    
    @user.before_request    # 针对user蓝图
    def befor1():
        print('我是us的befor1')
    
    @user.route('/user')
    def index():
        return 'ok'
    
    # pro_flask/views/blog.py
    from flask import Blueprint,url_for
    
    blog = Blueprint('blog',__name__)   # blog为名称空间, __name__为当前蓝图的所在文件
    
    @blog.before_request    # 针对blog蓝图
    def befor1():
        print("我是blog的befor1")
    
    @blog.route('/blog')
    def index():
        print(url_for('us.index'))  # 访问us名称空间中的index路径
        return 'blog'
    
    # pro_flask/views/blog.py
    from flask import Blueprint
    from flask import render_template
    from flask import request
    
    account = Blueprint('account', __name__)
    
    @account.route('/login.html', methods=['GET', "POST"])
    def login():
        return render_template('login.html')

    大型应用目录示例

    # run.py
    from pro_flask import app
    
    if __name__ == '__main__':
        app.run()
    
    # pro_flask/__init__.py
    from flask import Flask
    from .admin import admin
    from .web import web
    
    app = Flask(__name__)
    app.debug = True
    
    app.register_blueprint(admin, url_prefix='/admin')  # 只要访问吃蓝图,前面默认加上/admin前缀
    app.register_blueprint(web)
    
    # pro_flask/admin/__init__.py
    from flask import Blueprint
    
    admin = Blueprint(
        'admin',
        __name__,
        template_folder='templates',
        static_folder='static'
    )
    from . import views
    
    # pro_flask/admin/views.py
    from . import admin
    
    @admin.route('/index')
    def index():
        return 'Admin.Index'
    
    # pro_flask/web/__init__.py
    from flask import Blueprint
    
    web = Blueprint(
        'web',
        __name__,
        template_folder='templates',
        static_folder='static'
    )
    from . import views
    
    # pro_flask/web/views.py
    from . import web
    
    @web.route('/index')
    def index():
        return 'Web.Index'

    总结

    1 @app.before_first_request,再项目启动后接收到的第一个请求,会执行before_first_request,他再@app.before_request之前执行。他也可以有多个,谁先注册谁先执行。无论有没有返回值,后面都会执行。
    
    2 @app.before_request,再执行响应函数之前执行,他可以有多个,如果有多个谁先注册谁先执行,但是只要有一个有返回值,后面的before_request都会不执行,且响应函数也不执行。如果没有都befor_request返回值,那所有的before_request都会执行,且响应函数也会执行。
    
    3 @app.after_request,再执行befor_request和响应之后执行,他可以有多个,如果有多个谁先注册谁后执行。被after_request装饰的函数,必须接收响应,且必须把响应对象返回。对于@pp.before_request有没有返回值,@app.after_request都会执行。
    
    4@app.teardown_request,用来捕获错误,无论有没有错误都会执行。如果没有错误接收的错误就是none,如果有错误就会接收到错误。但是他不能处理错误。
    
    5@app.errorhandler(500),用来捕获错误,捕获哪种错误,必须把错误的状态码传入到errorhandle中,如果没有错误就不会执行,如果有错误就能处理错误,给用户良好的体验。
    
    6 @app.template_global(),相当于django中的标签,只要定义它,就可以再不把函数对象传递模板的情况下,再模板中直接使用。用法:{{函数名()}}
    
    7 @app.template_filter(),相当于django中的过滤器,它使用和django中的过滤一样的用,但是它可以接收多个参数,无论是几个。用法:{{要过滤的值|函数名(参数)}}
  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12554752.html
Copyright © 2011-2022 走看看