Flask入門到放棄(五)—— 藍圖
轉載請在文章開頭附上原文連結地址:https://www.cnblogs.com/Sunzz/p/10980094.html
藍圖 Blueprint
模組化
隨著flask程式越來越複雜,我們需要對程式進行模組化的處理,之前學習過python的模組化管理,於是針對一個簡單的flask程式進行模組化處理
簡單來說,Blueprint 是一個儲存檢視方法的容器,這些操作在這個Blueprint 被註冊到一個應用之後就可以被呼叫,Flask 可以通過Blueprint來組織URL以及處理請求。
Flask使用Blueprint讓應用實現模組化,在Flask中,Blueprint具有如下屬性:
- 一個專案可以具有多個Blueprint
- 可以將一個Blueprint註冊到任何一個未使用的URL下比如 “/”、“/sample”或者子域名
- 在一個應用中,一個模組可以註冊多次
- Blueprint可以單獨具有自己的模板、靜態檔案或者其它的通用操作方法,它並不是必須要實現應用的檢視和函式的
- 在一個應用初始化時,就應該要註冊需要使用的Blueprint
但是一個Blueprint並不是一個完整的應用,它不能獨立於應用執行,而必須要註冊到某一個應用中。
Blueprint物件用起來和一個應用/Flask物件差不多,最大的區別在於一個 藍圖物件沒有辦法獨立執行,必須將它註冊到一個應用物件上才能生效
使用藍圖可以分為四個步驟
- 建立一個藍圖的包,例如users,並在
__init__.py
users=Blueprint('users',__name__)
- 在這個藍圖目錄下, 建立views.py檔案,儲存當前藍圖使用的檢視函式
@admin.route('/')
def home():
return 'user.home'
- 在users/init.py中引入views.py中所有的檢視函式
from flask import Blueprint # 等同於原來在 manage.py裡面的 app = Flask() users=Blueprint('users',__name__) from .views import *
- 在主應用main.py檔案中的app物件上註冊這個users藍圖物件
from users import users
app.register_blueprint(users,url_prefix='/users')
當這個應用啟動後,通過/users/可以訪問到藍圖中定義的檢視函式
執行機制
- 藍圖是儲存了一組將來可以在應用物件上執行的操作,註冊路由就是一種操作
- 當在app物件上呼叫 route 裝飾器註冊路由時,這個操作將修改物件的url_map路由表
- 然而,藍圖物件根本沒有路由表,當我們在藍圖物件上呼叫route裝飾器註冊路由時,它只是在內部的一個延遲操作記錄列表defered_functions中添加了一個項
- 當執行app物件的 register_blueprint() 方法時,應用物件將從藍圖物件的 defered_functions 列表中取出每一項,並以自身作為引數執行該匿名函式,即呼叫應用物件的 add_url_rule() 方法,這將真正的修改應用物件的usr_map路由表
藍圖的url字首
- 當我們在應用物件上註冊一個藍圖時,可以指定一個url_prefix關鍵字引數(這個引數預設是/)
- 在應用最終的路由表 url_map中,在藍圖上註冊的路由URL自動被加上了這個字首,這個可以保證在多個藍圖中使用相同的URL規則而不會最終引起衝突,只要在註冊藍圖時將不同的藍圖掛接到不同的自路徑即可
- url_for在使用時,如果要生成一個藍圖裡面的檢視對應的路由地址,則需要聲明當前藍圖名稱+檢視名稱
url_for('users.home') # /users/home
註冊藍圖中的靜態檔案的相關路由
和應用物件不同,藍圖物件建立時不會預設註冊靜態目錄的路由。需要我們在 建立時指定 static_folder 引數。
下面的示例將藍圖所在目錄下的static_users目錄設定為靜態目錄
# users/__init__.py,程式碼:
user_blu = Blueprint("users",__name__,static_folder='static_users')
# 啟動檔案 main.py,程式碼:
from users import user_blu
app.register_blueprint(user_blu,url_prefix='/users')
現在就可以使用/admin/static_admin/ 訪問static_admin目錄下的靜態檔案了 定製靜態目錄URL規則 :可以在建立藍圖物件時使用 static_url_path 來改變靜態目錄的路由。
下面的示例將為 static_admin 資料夾的路由設定為 /lib
admin = Blueprint("admin",__name__,static_folder='static_admin',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')
設定藍圖中模版的目錄
藍圖物件預設的模板目錄為系統的模版目錄,可以在建立藍圖物件時使用 template_folder 關鍵字引數設定模板目錄
建立藍圖中的模板目錄template_users :
admin = Blueprint('admin',__name__,template_folder='templates_users')
注:如果在 templates 中存在和 templates_users 有同名模板檔案時, 則系統會優先使用 templates 中的檔案
調整session配置
分析SQLAlachemy的構造方式可以發現,初始化並非一定要傳遞app應用物件到內部,事實上它提供了init_app方法給我們後續呼叫。而 init_app 方法是flask框架要求任何的第三方元件都要實現這個方法。
init_app方法內部就是要第三方元件開發者編寫一些使用當前組建的預設配置項以及把當前元件設定成一個物件,載入到app物件內部extensions字典才能讓開發者在flask框架內部配置和使用當前元件。
我們可以利用這種元件開發機制,那麼把配置程式碼抽離出去。
配置檔案中:
import redis
from flask_sqlalchemy import SQLAlchemy
# 建立db物件
db = SQLAlchemy()
class Config(object):
DEBUG = True
SECRET_KEY = "*(%#4sxcz(^(#$#8423"
# 資料庫連結配置:
#資料型別://登入賬號:登入密碼@資料庫主機IP:資料庫訪問埠/資料庫名稱
SQLALCHEMY_DATABASE_URI = "mysql://root:[email protected]:3306/flask_students"
# 設定mysql的錯誤跟蹤資訊顯示
SQLALCHEMY_TRACK_MODIFICATIONS = True
# 列印每次模型操作對應的SQL語句
SQLALCHEMY_ECHO = True
"""把session儲存到redis中"""
# session儲存方式為redis
# SESSION_TYPE="redis"
# # 如果設定session的生命週期是否是會話期, 為True,則關閉瀏覽器session就失效
# SESSION_PERMANENT = False
# # 是否對傳送到瀏覽器上session的cookie值進行加密
# SESSION_USE_SIGNER = False
# # 儲存到redis的session數的名稱字首
# SESSION_KEY_PREFIX = "session:"
# # session儲存資料到redis時啟用的連結物件
# SESSION_REDIS = redis.Redis(host='127.0.0.1', port='6379') # 用於連線redis的配置
SESSION_TYPE= 'sqlalchemy' # session的儲存方式為sqlalchemy
SESSION_SQLALCHEMY= db # SQLAlchemy物件
SESSION_SQLALCHEMY_TABLE= 'sessions' # session要儲存的表名稱
SESSION_PERMANENT= True # 如果設定為True,則關閉瀏覽器session就失效。
SESSION_USE_SIGNER= False # 是否對傳送到瀏覽器上session的cookie值進行加密
SESSION_KEY_PREFIX= 'session:' # 儲存到session中的值的字首
啟動檔案main.py,程式碼:
from flask import Flask
from config import Config,db
from flask_session import Session
from flask import session
app = Flask(__name__,template_folder='templates')
app.config.from_object(Config)
# 把app載入到db物件中
db.init_app(app)
Session(app)
@app.route("/")
def index():
return "ok"
@app.route("/set_session")
def set_session():
"""設定session"""
session["username"] = "小明"
return "ok"
if __name__ == '__main__':
# db.create_all()
print( app.url_map )
app.run()