Flask07--請求擴展、中間件

一. 請求擴展

1. before_request

做用: 類比django中間件中的process_request,在請求到來執行路由函數以前先執行. 可是若是有多個順序是從上往下執行.html

應用: 基於它作用戶登陸認證python

注意: 若是before_request的返回值不是None的清空下, 返回的而是別的值, 那麼後續的請求都不會執行,本次請求直接返回, 若是定義了after_request那麼會接着它執行, 最終本次請求響應結束.django

@app.before_request
def process_request(*args,**kwargs):
    if request.path == '/login':
        return None
    user = session.get('user_info')
    if user:
        return None
    return redirect('/login')

2. after_request

做用: 類比django中間件中的process_response,若是請求沒有出現異常的狀況下, 會在請求返回return以前執行. 可是若是有多個順序是從下往上執行.flask

@app.after_request  # 後執行
def process_response1(response):
    print('process_response1 走了')
    return response

@app.after_request  # 先執行
def process_response2(response):
    print('process_response2 走了')
    return response

3. before_first_request

做用: 項目啓動起來接收到第一次請求時執行.服務器

應用: 項目初始化用來保證之後項目只要不重啓就再也不繼續執行.session

@app.before_first_request
def first():
    print('個人第一次')

4. teardown_request

做用: 在每個路由函數執行完畢以後執行,即便遇到了異常也會執行. (提示: 返回reutrn沒有任何的效果, 不能控制返回的結果)app

應用: 記錄日誌函數

@app.teardown_request  
def ter(e):  # e就是上一個路由函授執行過程當中出現被捕獲的異常信息.
    print(e)
    print('我是teardown_request ')

5. errorhandler

做用: 綁定錯誤的狀態碼進而能夠捕獲服務器的錯誤, 並返回對應的錯誤頁面.日誌

@app.errorhandler(500)
def error_500(arg):
    return render_template('error.html', message='500錯誤')


@app.errorhandler(404)
def error_404(arg):
    return render_template('error.html', message='404錯誤')

6. template_global

做用: 全局的標籤, 在任意的html頁面中就能夠直接使用, 不須要在render_template中傳遞參數之後才能使用.code

@app.template_global()
def sb(a1, a2):
    return a1 + a2
# html頁面中直接使用, 不須要傳遞參數.
{{ sb(1,2) }}

7. template_filter

做用: 全局的過濾器, 在任意的html頁面中就能夠直接使用, 不須要在render_template中傳遞參數之後才能使用.

@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3
{{1|db(2,3)}}

8. 模板上下文

@app.context_processor
def context_processor():
    return {"username":"馬克菠蘿"}

   app對象調用context_processor做爲模板上下文處理器,視圖函數在每一次調用render_template('')的時候都會爲模板傳入@app.context_processor裝飾器所裝飾函數的返回值,該返回值做爲模板變量,可是返回值必定要爲字典,若是不想返回任何值,能夠返回空字典,不然會報錯,返回值能夠設置爲模板常常要使用的變量,減小了代碼的冗餘,提升了代碼的可維護性。
# html頁面中直接使用, 不須要傳遞參數. 其中1傳遞給a1, 2傳遞給a2, 3傳遞給a3. (提示: Django中的過濾器最多隻能夠傳遞二個參數)

二 flask的中間件:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    print('視圖函數中')
    return 'hello world'

class my_middle:

    def __init__(self,wsgi_app):
        self.wsgi_app = wsgi_app

    def __call__(self, *args, **kwargs):
        print('中間件的代碼上')
        obj = self.wsgi_app( *args, **kwargs)
        print('中間件的代碼下')

        return obj

if __name__ == '__main__':
   
    app.wsgi_app = my_middle(app.wsgi_app)
     # app.wsgi_app(environ, start_response)
    app.run()
    # 梳理一下 根據werkzeug咱們能夠知道 每次請求必然經歷了app()
    # 因此咱們要查看Flask的源碼找到__call__方法
    # 找到了__call__方法後發現執行了return self.wsgi_app(environ, start_response)
    # 而後flask裏面全部的內容調度都是基於這個self.wsgi_app(environ, start_response),這就是就是flask的入口
    # 如何實現中間件呢? 原理上就是重寫app.wsgi_app,而後在裏面添加上一些本身想要實現的功能。
    # 首先分析  app.wsgi_app須要加括號執行  因此咱們把app.wsgi_app作成一個對象,而且這個對象須要加括號運行
    # 也就是會觸發這個對象的類的__call__()方法
    # 1 那麼就是app.wsgi_app=對象=本身重寫的類(app.wsgi_app) ,咱們須要在本身重寫的類裏面實現flask源碼中的app.wsgi_app,在實例化的過程把原來的app.wsgi_app變成對象的屬性
    # 2         app.wsgi_app() =對象() = 本身重寫的類.call()方法
    # 3         那麼上面的代碼就能夠理解了,在本身重寫的類中實現了原有的__call__方法
相關文章
相關標籤/搜索