
timg (7).jpg
在上一節
Python Flask學習知識點(二)文章中,
把視圖函數從入口啟動檔案中分離了出來,把視圖函數放到了book.py子產品中,但是通過嘗試,無法從啟動檔案run.py中導入Flask核心對象app,這也就導緻無法使用Flask核心對象來注冊視圖函數的路由,解決這個問題的方法有很多種。
引入藍圖概念
Flask提供了一種機制,叫做藍圖(blueprint)
Flask 中的藍圖為這些情況設計:
- 把一個應用分解為一個藍圖的集合。這對大型應用是理想的。一個項目可以執行個體化一個應用對象,初始化幾個擴充,并注冊一集合的藍圖。
- 以 URL 字首和/或子域名,在應用上注冊一個藍圖。 URL 字首/子域名中的參數即成為這個藍圖下的所有視圖函數的共同的視圖參數(預設情況下)。
- 在一個應用中用不同的 URL 規則多次注冊一個藍圖。
- 通過藍圖提供模闆過濾器、靜态檔案、模闆和其它功能。一個藍圖不一定要實作應用或者視圖函數。
- 初始化一個 Flask 擴充時,在這些情況中注冊一個藍圖。
層級關系如下圖:
image.png
Flask中,app可以看作是一個插線闆,上邊可以插很多的藍圖,藍圖不能獨立存在,必須插入到Flask核心對象app中;
app也可以插入很多Flask插件;
藍圖下邊是視圖函數,還可以指定靜态檔案夾和模闆檔案夾。
我們可以注冊很多藍圖,把分類不同的視圖函數注冊到特定的藍圖上,例如:book.py中的視圖函數可以注冊到它的藍圖上。
上圖中,web這個層級就是藍圖。
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=app.config['DEBUG'], port=83)
随着項目擴充增大,需要在Flask核心對象app上注冊各種各樣插件,包括藍圖,也就是說初始化代碼會越來越複雜,當代碼變複雜是,就要想辦法去簡化、優化、分離,是以現在要把Flask初始化操作從啟動檔案中分離出去。
在app檔案夾下建立
__init__.py
檔案,
from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object("config")
return app
然後在run.py中導入app
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=app.config['DEBUG'], port=81)
至此,應用級别的初始化完成。
用藍圖注冊視圖函數
藍圖初始化:
在web檔案夾下建立
__init__.py
,藍圖有關的初始化都放到這裡。
編輯book.py檔案:
from flask import jsonify, Blueprint
web = Blueprint('web', __name__)
@web.route('/hello')
def search():
result = {'key1': 'a'}
return jsonify(result)
上邊代碼,把視圖函數注冊到了藍圖上,接着,要把藍圖注冊到Flask核心對象app上,
藍圖注冊到app上是關于app的操作,是以放到app檔案夾下
__init__.py中
,更改
__init__.py
:
from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object("config")
register_blueprint(app)
return app
def register_blueprint(app):
from app.web.book import web
app.register_blueprint(web)
運作run.py可以得到視圖函數傳回的JSON
可以debug調試看下:
url_map和view_functions都有對應值,由于是因為視圖函數注冊到藍圖,藍圖再到app,是以顯示為藍圖名稱web下的search視圖函數。
單藍圖多子產品
上邊代碼中,在web這個藍圖中隻有一個子產品book.py,如果我們要想再增加一個user.py子產品,就必須再建立一個藍圖,顯然不合理,這是wo
藍圖其實是在大型工程中分拆不同子產品的。
怎麼了解上邊這句話?
上邊截圖中,app檔案夾之下的三個檔案夾可以視為三個藍圖,
web:提供給網站相關模闆和檔案
api:給移動端提供資料
cms:提供内容管理
如何在同一個藍圖下,把視圖函數拆分到不同子產品?
把book.py中藍圖的代碼放到web檔案夾下
__init__.py
中:
from flask import Blueprint
# 藍圖
web = Blueprint("web", __name__)
再更改book.py
from flask import jsonify
from . import web
__author__ = 'Allen'
@web.route('/hello/')
def search():
result = {'key1': 'ab'}
return jsonify(result)
至此,就實作了同一個藍圖下,把視圖函數拆分到不同子產品。
Flask中request對象
視圖函數傳參方式,
先看第一種:
from flask import jsonify
from . import web
@web.route('/hello/<q>/<page>')
def search(q, page):
result = {q: page}
return jsonify(result)
通路
127.0.0.1:81/hello/a/b
,傳回的是{"a":"b"}
(這裡提示下,如果通路404,浏覽器清空緩存再試)
現在改寫URL傳參模式,改成這樣:
127.0.0.1:81/hello?q=小明&page=3
代碼就要這麼寫:
from flask import jsonify, request
from . import web
@web.route('/hello/')
def search():
q = request.args['q']
page = request.args['page']
result = {"name": q, "valus": page}
return jsonify(result)
導入Flask内置的request對象來擷取傳入的參數q和page
絕大多數的web架構中管理http請求和響應時,都需要這樣的類,一個是request,一個是response
request中包含了很多資訊,包含全部的HTTP請求資訊,GET POST 通路來源的ip(remote ip),這裡隻舉着幾個例子,其餘的請檢視文檔。
request.agrs
并不是dict而是dict子類,是以可以像通路字典那樣通路資料,最大特點是不可變,元組和字元串是可變如果想要實作不可變字典 ,可以自己繼承dict寫方法,但是Flask中已經内置了這種方法,request.args.to_dict() flask字典轉換為常見普通字典。
request使用必須是在flask上下文環境中,是由http請求觸發的,因為flask request使用的代理模式,這個後續會深入講解。
欲知後事如何,請看下回分解,記得點個贊~感謝