Flask入門很輕鬆 (二)

轉載請在文章開頭附上原文連接地址:http://www.javashuo.com/article/p-vakmmhen-ks.htmlhtml

請求鉤子

在客戶端和服務器交互的過程當中,有些準備工做或掃尾工做須要處理,好比:python

  • 在請求開始時,創建數據庫鏈接;
  • 在請求開始時,根據需求進行權限校驗;
  • 在請求結束時,指定數據的交互格式;

爲了讓每一個視圖函數避免編寫重複功能的代碼,Flask提供了通用設置的功能,即請求鉤子。數據庫

請求鉤子是經過裝飾器的形式實現,Flask支持以下四種請求鉤子:json

  • before_first_request
    • 在處理第一個請求前執行
  • before_request
    • 在每次請求前執行
    • 若是在某修飾的函數中返回了一個響應,視圖函數將再也不被調用
  • after_request
    • 若是沒有拋出錯誤,在每次請求後執行
    • 接受一個參數:視圖函數做出的響應
    • 在此函數中能夠對響應值在返回以前作最後一步修改處理
    • 須要將參數中的響應在此參數中進行返回
  • teardown_request:
    • 在每次請求後執行
    • 接受一個參數:錯誤信息,若是有相關錯誤拋出
    • 須要設置flask的配置DEBUG=False,teardown_request纔會接受到異常對象。

代碼flask

config.pybash

class Config(object):
    DEBUG = True
    SECRET_KEY = "abcccddgadsag"

hook.py服務器

from flask import Flask
from config import Config

app = Flask(__name__)
app.config.from_object(Config)

@app.before_first_request
def before_firest_request():
    print("----- before_first_requets-----")
    print("系統初始化的時候,執行這個鉤子方法")
    print("會在接收到第一個用戶請求時,執行這裏的代碼")


@app.before_request
def before_request():
    print("----before request")
    print("每一次接收到用戶請求時,執行這個鉤子方法")
    print("通常能夠用來判斷權限,或者轉換路由參數或者預處理客戶端的請求的數據")


@app.after_request
def after_request(response):
    print("----after_request----")
    print("在處理請求之後,執行這個鉤子方法")
    print("通常能夠用於記錄會員/管理員的操做歷史,瀏覽歷史,清理收尾的工做")
    response.headers["Content-Type"] = "application/json"
    return response


@app.teardown_request
def teardown_request(exc):
    print("----teardown_request----")
    print("在每一次請求之後,執行這個鉤子方法,若是有異常錯誤,則會傳遞錯誤異常對象到當前方法的參數中")
    print(exc)


@app.route("/hook")
def hook():
    print("----這是視圖函數----")
    print("視圖函數被運行了")
    return "這是視圖函數"


if __name__ == '__main__':
    app.run(host="127.0.0.1", port=80)
  • 請求時的打印:
----- before_first_requets-----
系統初始化的時候,執行這個鉤子方法
會在接收到第一個用戶請求時,執行這裏的代碼
----before request
每一次接收到用戶請求時,執行這個鉤子方法
通常能夠用來判斷權限,或者轉換路由參數或者預處理客戶端的請求的數據
----這是視圖函數----
視圖函數被運行了
----after_request----
在處理請求之後,執行這個鉤子方法
通常能夠用於記錄會員/管理員的操做歷史,瀏覽歷史,清理收尾的工做
----teardown_request----
在每一次請求之後,執行這個鉤子方法,若是有異常錯誤,則會傳遞錯誤異常對象到當前方法的參數中
None

異常捕獲

主動拋出HTTP異常

  • abort 方法
    • 拋出一個給定狀態代碼的 HTTPException 或者 指定響應,例如想要用一個頁面未找到異常來終止請求,你能夠調用 abort(404)。
  • 參數:
    • code – HTTP的錯誤狀態碼
# abort(404)
abort(500)

拋出狀態碼的話,只能拋出 HTTP 協議的錯誤狀態碼cookie

捕獲錯誤

  • errorhandler 裝飾器
    • 註冊一個錯誤處理程序,當程序拋出指定錯誤狀態碼的時候,就會調用該裝飾器所裝飾的方法
  • 參數:
    • code_or_exception – HTTP的錯誤狀態碼或指定異常
  • 例如統一處理狀態碼爲500的錯誤給用戶友好的提示:
@app.errorhandler(500)
def internal_server_error(e):
    return '服務器搬家了'
  • 捕獲指定異常類型
@app.errorhandler(ZeroDivisionError)
def zero_division_error(e):
    return '除數不能爲0'

上下文

上下文:即語境,語意,在程序中能夠理解爲在代碼執行到某一時刻時,根據以前代碼所作的操做以及下文即將要執行的邏輯,能夠決定在當前時刻下能夠使用到的變量,或者能夠完成的事情。session

Flask中有兩種上下文,請求上下文(request context)和應用上下文(application context)。app

Flask中上下文對象:至關於一個容器,保存了 Flask 程序運行過程當中的一些信息。

  1. application 指的就是當你調用app = Flask(__name__)建立的這個對象app
  2. request 指的是每次http請求發生時,WSGI server(好比gunicorn)調用Flask.__call__()以後,在Flask對象內部建立的Request對象;
  3. application 表示用於響應WSGI請求的應用自己,request 表示每次http請求;
  4. application的生命週期大於request,一個application存活期間,可能發生屢次http請求,因此,也就會有多個request

請求上下文(request context)

思考:在視圖函數中,如何取到當前請求的相關數據?好比:請求地址,請求方式,cookie等等

在 flask 中,能夠直接在視圖函數中使用 request 這個對象進行獲取相關數據,而 request 就是請求上下文的對象,保存了當前本次請求的相關數據,請求上下文對象有:request、session

  • request
    • 封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。
  • session
    • 用來記錄請求會話中的信息,針對的是用戶信息。舉例:session['name'] = user.id,能夠記錄用戶信息。還能夠經過session.get('name')獲取用戶信息。

應用上下文(application context)

它的字面意思是 應用上下文,但它不是一直存在的,它只是request context 中的一個對 app 的代理(人),所謂local proxy。它的做用主要是幫助 request 獲取當前的應用,它是伴 request 而生,隨 request 而滅的。

應用上下文對象有:current_app,g

current_app

應用程序上下文,用於存儲應用程序中的變量,能夠經過current_app.name打印當前app的名稱,也能夠在current_app中存儲一些變量,例如:

  • 應用的啓動腳本是哪一個文件,啓動時指定了哪些參數
  • 加載了哪些配置文件,導入了哪些配置
  • 鏈接了哪一個數據庫
  • 有哪些能夠調用的工具類、常量
  • 當前flask應用在哪一個機器上,哪一個IP上運行,內存多大
current_app.name
current_app.test_value='value'

g變量

g 做爲 flask 程序全局的一個臨時變量,充當者中間媒介的做用,咱們能夠經過它傳遞一些數據,g 保存的是當前請求的全局變量,不一樣的請求會有不一樣的全局變量,經過不一樣的thread id區別

g.name='abc'

注意:不一樣的請求,會有不一樣的全局變量

二者區別:

  • 請求上下文:保存了客戶端和服務器交互的數據
  • 應用上下文:flask 應用程序運行過程當中,保存的一些配置信息,好比程序名、數據庫鏈接、應用信息等
from flask import Flask
# 新增一個配置文件,在配置文件中設置配置信息
from config import Config
from flask import request

app = Flask(__name__)
app.config.from_object(Config)



"""請求上下文"""
class Model(object):
    def __init__(self):
        print("模型接受到數據,num=%s" % request.args.get("username") )

@app.route("/context")
def context():
    Model()
    return "ok"

@app.route("/context2")
def context2():
    Model()
    return "ok"

"""應用上下文"""
from flask import current_app
@app.route('/context3')
def context3():

    # current_app 只是app對象在視圖被請求時的一個代理對象[別名對象]
    print( current_app.username ) # 咱們能夠直接調用app對象所擁有的屬性和方法
    return "應用上下文"

from flask import g
class Model2(object):
    def __init__(self):
        print("模型接受到數據,num=%s" % g.username )



@app.route('/context4')
def context4():
    # g是一個臨時的全局對象,只會在本次請求中獲取到數據
    g.username = request.args.get("username")
    Model2()
    return "應用上下文"

if __name__ == '__main__':
    # app 系統應用對象
    app.username='應用上下文的username'
    print('----運行項目以前----')
    app.run()

Flask-Script 擴展

安裝命令:

pip install flask-script

集成 Flask-Script到flask應用中

from flask import Flask

app = Flask(__name__)

"""使用flask_script啓動項目"""
from flask_script import Manager
manage = Manager(app)

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

if __name__ == "__main__":
    manager.run()

Flask-Script 還能夠爲當前應用程序添加腳本命令

"""自定義flask_script終端命令"""
from flask_script import Command
class HelloCommand(Command):
    """命令的相關描述"""
    def run(self):
        with open("text.txt","w") as f:
            f.write("hello\r\nhello")
            pass

        print("這是執行了hello命令")

manage.add_command('hello', HelloCommand() )
相關文章
相關標籤/搜索