目錄
1.通過終端命令建立藍圖,並在藍圖中生成view/model/url等檔案
1.準備工作
1.新建專案目錄mofangapi,並建立虛擬環境
mkvirtualenv mofang
2.安裝開發中使用的依賴模組
pip install flask==0.12.4 pip install flask-redis pip install flask-session pip install flask-script pip install flask-mysqldb pip install flask-sqlalchemy pip install flask-migrate
接下來,在pycharm中開啟專案目錄mofangapi編寫manage.py啟動專案的檔案
2.建立專案啟動檔案manage.py
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'index' if __name__ == '__main__': app.run()
manage.py終不能存放大量的開發程式碼, 在開發中應該體現的是一種分工精神,所以我們可以把flask中各種功能程式碼進行分類分檔案儲存.
現在專案的目錄結構如下所示:
專案根目錄/ ├── application/ # 專案主要邏輯程式碼儲存目錄 | ├── settings/ # 專案配置儲存目錄 │ │ ├ dev.py # 開發階段的配置檔案 │ │ ├ prod.py # 生產階段的配置檔案 | | ├ __init__.py # 專案公共配置檔案 │ ├── __init__.py # 專案初始化檔案 ├── manage.py # 專案的終端管理指令碼檔案
3.
from flask import Flask def init_app(): """全域性初始化""" app = Flask(__name__) # 建立APP應用物件 return app
2.在manage.py,中呼叫初始化函式,建立app應用物件,程式碼:
from application import init_app app = init_app() # 建立app應用物件 @app.route('/') def index(): return 'index' if __name__ == '__main__': app.run()
4.通過終端指令碼啟動專案
from flask import Flask from flask_script import Manager manager = Manager() # 引入終端指令碼管理物件 *** def init_app(): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) # 初始化終端指令碼工具 *** manager.app = app return manager
將manage.py的app改為manage,程式碼:
from application import init_app manage = init_app() @manage.app.route('/') def index(): return 'index' if __name__ == '__main__': manage.run()
執行專案的方式就要修改如下:
此時我們就可以通過如下指令去執行專案了
python manage.py runserver -h0.0.0.0 -p5000
5.專案載入配置
1.在application/utils/config.py中準備載入配置的函式程式碼:
from importlib import import_module def load_config(config_path): """自動載入配置""" module = import_module(config_path) name = config_path.split(".")[-1] if name == "settings": return module.InitConfig else: return module.Config
class InitConfig(): """專案預設初始化配置""" DEBUG = True
當然, 專案開發過程完成以後肯定會專案上線,所以針對配置檔案,我們可以準備不同環境下的配置
application/settings/dev.py
,程式碼:
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" DEBUG = True
from . import InitConfig class Config(InitConfig): """專案運營環境下的配置""" DEBUG = False
from flask import Flask from flask_script import Manager from application.utils.config import load_config manager = Manager() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) # 設定專案根目錄 app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 **** Config = load_config(config_path) # 呼叫utils裡自己已經寫好的load_config方法 app.config.from_object(Config) # 將配置類註冊到APP上 # 初始化終端指令碼工具 manager.app = app return manager
4.在建立app物件的專案啟動檔案manage.py中,設定配置
from application import init_app manage = init_app("application.settings.dev") # 設定預設專案使用的配置檔案是dev.py @manage.app.route('/') def index(): return 'index' if __name__ == '__main__': manage.run()
6.資料庫初始化
1.SQLAlchemy初始化
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" DEBUG = True # 資料庫 SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4" SQLALCHEMY_ECHO = True
3.在mysql終端下, 建立資料庫使用者,命令如下:
create database mofang charset=utf8mb4; # 針對當前資料庫配置賬戶資訊 create user mofang_user identified by 'mofang'; grant all privileges on mofang.* to 'mofang_user'@'%'; flush privileges;
from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from application.utils.config import load_config # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 *** db = SQLAlchemy() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) # 專案根目錄 app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 *** db.init_app(app) # 初始化終端指令碼工具 manager.app = app return manager
2.Redis初始化
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True # Redis REDIS_URL = "redis://@127.0.0.1:6379/0"
from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from application.utils.config import load_config # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 *** redis = FlaskRedis() def init_app(config_path): """全域性初始化"""
# 建立app應用物件 app = Flask(__name__) # 專案根目錄 app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # redis資料庫初始化 *** # 初始化終端指令碼工具 manager.app = app return manager
3.session儲存到redis資料庫中
from redis import Redis def init_session(app): host = app.config.get("SESSION_REDIS_HOST","127.0.0.1") port = app.config.get("SESSION_REDIS_PORT",6379) db = app.config.get("SESSION_REDIS_DB",0) print(db) app.config["SESSION_REDIS"] = Redis(host=host,port=port,db=db)
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True # Redis REDIS_URL = "" # 設定金鑰,可以通過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字串 *** SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw" '''session儲存配置''' *** # session儲存方式配置 *** SESSION_TYPE = "redis" # 如果設定session的生命週期是否是會話期, 為True,則關閉瀏覽器session就失效 *** SESSION_PERMANENT = False # 設定session_id在瀏覽器中的cookie有效期 *** PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒 *** # 是否對傳送到瀏覽器上session的cookie值進行加密 *** SESSION_USE_SIGNER = True # 儲存到redis的session數的名稱字首 *** SESSION_KEY_PREFIX = "session:" # session儲存資料到redis時啟用的連結物件 *** SESSION_REDIS = None # 用於連線redis的配置 *** SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 0
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" DEBUG = True # 資料庫 SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4" SQLALCHEMY_ECHO = True # redis *** REDIS_URL = "redis://@127.0.0.1:6379/0" # 0號redis庫用來存redis快取 # session儲存配置 *** SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 1號redis庫用來存session
from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from flask_session import Session from application.utils.config import load_config from application.utils.session import init_session # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 redis = FlaskRedis() # Session儲存物件 *** session_store = Session() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) # 專案根目錄 app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # session儲存初始化 *** init_session(app) # 載入session配置 session_store.init_app(app) # session儲存初始化 # 初始化終端指令碼工具 manager.app = app return manager
4.資料遷移初始化
from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from flask_session import Session from flask_migrate import Migrate,MigrateCommand # *** from application.utils.config import load_config from application.utils.session import init_session # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 redis = FlaskRedis() # Session儲存物件 session_store = Session() # 資料遷移例項物件 *** migrate = Migrate() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) # 專案根目錄 app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # session儲存初始化 init_session(app) session_store.init_app(app) # 資料遷移初始化 *** migrate.init_app(app,db) # 新增資料遷移的命令到終端指令碼工具中 *** manager.add_command('db', MigrateCommand) # 初始化終端指令碼工具 manager.app = app return manager
完成上面的專案構建步驟以後,此時目錄結構如下:
專案根目錄/ ├── docs/ # 專案開發文件/介面等備份資料儲存目錄 ├── logs/ # 專案日誌儲存目錄 ├── application/ # 專案主要邏輯程式碼儲存目錄 | ├── settings/ # 專案配置儲存目錄 │ │ ├ dev.py # 開發階段的配置檔案 │ │ ├ prod.py # 生產階段的配置檔案 | | ├ __init__.py # 專案公共配置檔案 | ├── utils/ # 工具函式庫/類庫 │ │ ├ session.py # session相關的輔助函式 │ │ ├ config.py # 配置相關的輔助函式 │ ├── __init__.py # 專案初始化檔案 └── manage.py # 專案的終端管理指令碼檔案
7.日誌初始化
flask中沒有內建的日誌功能,我們在使用的時候, 一般日誌如果不是核心重點,則通過由python內建的logging模組進行配置整合使用即可, 如果專案中日誌發揮作用比較重要, 則一般安裝部署 ELK日誌分析系統.
1.日誌的等級
FATAL/CRITICAL = 致命的,危險的 ERROR = 錯誤 WARNING = 警告 INFO = 資訊 DEBUG = 除錯
2.構建日誌模組
import logging from logging.handlers import RotatingFileHandler class Log(): """日誌模組""" def __init__(self, app=None): if app is not None: self.init_app(app) def init_app(self,app): self.app = app return self.setup() def setup(self): """安裝日誌功能到flask中""" # 設定日誌的記錄等級 logging.basicConfig(level=self.app.config.get("LOG_LEVEL")) # 除錯debug級 # 建立日誌記錄器,指明日誌儲存的路徑、每個日誌檔案的最大大小、儲存的日誌檔案個數上限 file_log_handler = RotatingFileHandler( self.app.BASE_DIR+self.app.config.get("LOG_DIR"), maxBytes=self.app.config.get("LOG_MAX_BYTES"), backupCount=self.app.config.get("LOG_BACKPU_COUNT") ) # 建立日誌記錄的格式 日誌等級 輸入日誌資訊的檔名 行數 日誌資訊 formatter = logging.Formatter('%(name)s: %(levelname)s %(asctime)s %(filename)s:%(lineno)d %(message)s') # 為剛建立的日誌記錄器設定日誌記錄格式 file_log_handler.setFormatter(formatter) # 為全域性的日誌工具物件(flaskapp使用的)新增日誌記錄器 logging.getLogger(self.app.config.get("LOG_NAME")).addHandler(file_log_handler) # 返回日誌器物件提供給業務開發 logger = logging.getLogger(self.app.config.get("LOG_NAME")) return logger
2.application/settings/__init__.py
程式碼:
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True # Redis REDIS_URL = "" # 設定金鑰,可以通過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字串 SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw" # session儲存配置 # session儲存方式配置 SESSION_TYPE = "redis" # 如果設定session的生命週期是否是會話期, 為True,則關閉瀏覽器session就失效 SESSION_PERMANENT = False # 設定session_id在瀏覽器中的cookie有效期 PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒 # 是否對傳送到瀏覽器上session的cookie值進行加密 SESSION_USE_SIGNER = True # 儲存到redis的session數的名稱字首 SESSION_KEY_PREFIX = "session:" # session儲存資料到redis時啟用的連結物件 SESSION_REDIS = None # 用於連線redis的配置 SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 調整json資料轉換中文的配置 JSON_AS_ASCII=False # 日誌相關配置 *** LOG_LEVEL = "INFO" # 日誌輸出到檔案中的最低等級 LOG_DIR = "logs/0.log" # 日誌儲存目錄 LOG_MAX_BYTES = 300 * 1024 * 1024 # 單個日誌檔案的儲存上限[單位: b] LOG_BACKPU_COUNT = 20 # 日誌檔案的最大備份數量 LOG_NAME = "flask" # 日誌器的名字
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" DEBUG = True # 資料庫 SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4" SQLALCHEMY_ECHO = True # redis REDIS_URL = "redis://@127.0.0.1:6379/0" # session儲存配置 SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 日誌配置 *** LOG_LEVEL = "DEBUG" # 日誌輸出到檔案中的最低等級 LOG_DIR = "/logs/mofang.log" # 日誌儲存目錄 LOG_MAX_BYTES = 300 * 1024 * 1024 # 單個日誌檔案的儲存上限[單位: b] LOG_BACKPU_COUNT = 20 # 日誌檔案的最大備份數量 LOG_NAME = "mofang" # 日誌器名稱
import os,logging from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from flask_session import Session from flask_migrate import Migrate,MigrateCommand from application.utils.config import load_config from application.utils.session import init_session from application.utils.logger import Log # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 redis = FlaskRedis() # Session儲存物件 session_store = Session() # 資料遷移例項物件 migrate = Migrate() # 日誌物件 *** log = Log() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # session儲存初始化 init_session(app) session_store.init_app(app) # 資料遷移初始化 migrate.init_app(app,db) # 新增資料遷移的命令到終端指令碼工具中 manager.add_command('db', MigrateCommand) # 日誌初始化 *** app.log = log.init_app(app) # 初始化終端指令碼工具 manager.app = app return manager
新增日誌的專案目錄結構如下所示
├── application │ ├── __init__.py │ ├── settings │ │ ├── dev.py │ │ ├── __init__.py │ │ ├── prod.py │ └── utils │ ├── config.py │ ├── __init__.py │ ├── logger.py # 日誌相關模組程式碼庫 │ └── session.py ├── docs ├── logs # 日誌檔案儲存目錄 │ └── mofang.log └── manage.py
經過上面的改造,我們接下來就可以開始建立藍圖了。
8.藍圖初始化
1.通過終端命令建立藍圖,並在藍圖中生成view/model/url等檔案
from flask_script import Command, Option class BlueprintCommand(Command): """藍圖生成命令""" name = "blue" option_list = [ Option('--name', '-n', dest='name'), ] def run(self, name): # 生成藍圖名稱物件的目錄 os.mkdir(name) open("%s/__init__.py" % name, "w") open("%s/views.py" % name, "w") open("%s/models.py" % name, "w") with open("%s/urls.py" % name, "w") as f: content = """from . import views from application.utils import path urlpatterns = [ ]""" f.write(content) print("藍圖%s建立完成...." % name)
但是, 我們往後的開發中肯定還會繼續的需要進行自定義終端命令,所以我們宣告一個load_command的函式,讓自動幫我們完成載入註冊自定義終端命令的過程.
import os from importlib import import_module from flask_script import Command, Option import inspect def load_command(manager,command_path=None): """自動載入自定義終端命令""" if command_path is None: command_path = "application.utils.commands" module = import_module(command_path) class_list = inspect.getmembers(module,inspect.isclass) for class_item in class_list: if issubclass(class_item[1],Command) and class_item[0] != "Command": manager.add_command(class_item[1].name,class_item[1]) class BlueprintCommand(Command): """藍圖生成命令""" name = "blue" option_list = [ Option('--name', '-n', dest='name'), ] def run(self, name): # 生成藍圖名稱物件的目錄 os.mkdir(name) open("%s/__init__.py" % name, "w") open("%s/views.py" % name, "w") open("%s/models.py" % name, "w") with open("%s/urls.py" % name, "w") as f: content = """from . import views from application.utils import path urlpatterns = [ ]""" f.write(content) print("藍圖%s建立完成...." % name)
import os,logging from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from flask_session import Session from flask_migrate import Migrate,MigrateCommand from application.utils.config import load_config from application.utils.session import init_session from application.utils.logger import Log from application.utils.commands import load_command # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 redis = FlaskRedis() # Session儲存物件 session_store = Session() # 資料遷移例項物件 migrate = Migrate() # 日誌物件 log = Log() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # session儲存初始化 init_session(app) session_store.init_app(app) # 資料遷移初始化 migrate.init_app(app,db) # 新增資料遷移的命令到終端指令碼工具中 manager.add_command('db', MigrateCommand) # 日誌初始化 app.log = log.init_app(app) # 初始化終端指令碼工具 manager.app = app # 註冊自定義命令 *** load_command(manager) return manager
命令:
cd application/apps
python ../../manage.py blue -nhome
效果:
專案中可以有多個藍圖,但是有些藍圖可能並不能提供給客戶端訪問,所以我們需要在配置檔案中宣告一個藍圖註冊列表, 在init_blueprint
函式中只註冊配置列表的藍圖
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True # Redis REDIS_URL = "" # 設定金鑰,可以通過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字串 SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw" # session儲存配置 # session儲存方式配置 SESSION_TYPE = "redis" # 如果設定session的生命週期是否是會話期, 為True,則關閉瀏覽器session就失效 SESSION_PERMANENT = False # 設定session_id在瀏覽器中的cookie有效期 PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒 # 是否對傳送到瀏覽器上session的cookie值進行加密 SESSION_USE_SIGNER = True # 儲存到redis的session數的名稱字首 SESSION_KEY_PREFIX = "session:" # session儲存資料到redis時啟用的連結物件 SESSION_REDIS = None # 用於連線redis的配置 SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 調整json資料轉換中文的配置 JSON_AS_ASCII=False # 日誌相關配置 LOG_LEVEL = "INFO" # 日誌輸出到檔案中的最低等級 LOG_DIR = "logs/0.log" # 日誌儲存目錄 LOG_MAX_BYTES = 300 * 1024 * 1024 # 單個日誌檔案的儲存上限[單位: b] LOG_BACKPU_COUNT = 20 # 日誌檔案的最大備份數量 LOG_NAME = "flask" # 日誌器的名字 # 藍圖註冊列表 *** INSTALLED_APPS = [ ]
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" DEBUG = True # 資料庫 SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4" SQLALCHEMY_ECHO = True # redis REDIS_URL = "redis://@127.0.0.1:6379/0" # session儲存配置 SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 日誌配置 LOG_LEVEL = "DEBUG" # 日誌輸出到檔案中的最低等級 LOG_DIR = "/logs/mofang.log" # 日誌儲存目錄 LOG_MAX_BYTES = 300 * 1024 * 1024 # 單個日誌檔案的儲存上限[單位: b] LOG_BACKPU_COUNT = 20 # 日誌檔案的最大備份數量 LOG_NAME = "mofang" # 日誌器名稱 # 註冊藍圖 *** INSTALLED_APPS = [ "application.apps.home", ]
2.在init_blueprint函式中,針對註冊的藍圖列表註冊到app應用物件裡面,
def init_blueprint(app): """自動註冊藍圖""" blueprint_path_list = app.config.get("INSTALLED_APPS") for blueprint_path in blueprint_path_list: blueprint_name = blueprint_path.split(".")[-1] # 自動建立藍圖物件 blueprint = Blueprint(blueprint_name,blueprint_path) # 註冊藍圖物件到app應用物件中 app.register_blueprint(blueprint,url_prefix="")
import os,logging from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_redis import FlaskRedis from flask_session import Session from flask_migrate import Migrate,MigrateCommand from application.utils import init_blueprint from application.utils.config import load_config from application.utils.session import init_session from application.utils.logger import Log from application.utils.commands import load_command # 建立終端指令碼管理物件 manager = Manager() # 建立資料庫連結物件 db = SQLAlchemy() # redis連結物件 redis = FlaskRedis() # Session儲存物件 session_store = Session() # 資料遷移例項物件 migrate = Migrate() # 日誌物件 log = Log() def init_app(config_path): """全域性初始化""" # 建立app應用物件 app = Flask(__name__) app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 載入配置 Config = load_config(config_path) app.config.from_object(Config) # 資料庫初始化 db.init_app(app) redis.init_app(app) # session儲存初始化 init_session(app) session_store.init_app(app) # 資料遷移初始化 migrate.init_app(app,db) # 新增資料遷移的命令到終端指令碼工具中 manager.add_command('db', MigrateCommand) # 日誌初始化 app.log = log.init_app(app) # 藍圖註冊 *** init_blueprint(app) # 初始化終端指令碼工具 manager.app = app # 註冊自定義命令 load_command(manager) return manager
所以, 在藍圖home下面的urls.py檔案中,通過path方法把url地址和檢視方法進行處理成字典,然後把字典作為成員返回到變數urlpatterns列表中.
from flask import Blueprint from importlib import import_module def path(rule,func_view): # 把藍圖下檢視和路由之間的對映關係處理成字典結構,方便後面註冊藍圖的時候,直接傳參 return {"rule":rule,"view_func":func_view}
from . import views from application.utils import path urlpatterns = [ path("/",views.index), ]
檢視程式碼:
def index(): return 'index'
3.在init_blueprint初始化藍圖的函式中, 生成藍圖物件以後自動載入並註冊藍圖和檢視
from flask import Blueprint from importlib import import_module def path(rule,func_view): # 把藍圖下檢視和路由之間的對映關係處理成字典結構,方便後面註冊藍圖的時候,直接傳參 return {"rule":rule,"view_func":func_view} def init_blueprint(app): """自動註冊藍圖""" blueprint_path_list = app.config.get("INSTALLED_APPS") for blueprint_path in blueprint_path_list: blueprint_name = blueprint_path.split(".")[-1] # 自動建立藍圖物件 blueprint = Blueprint(blueprint_name,blueprint_path) # 藍圖自動註冊和繫結檢視和子路由 url_module = import_module(blueprint_path+".urls") # 載入藍圖下的子路由檔案 for url in url_module.urlpatterns: # 遍歷子路由中的所有路由關係 blueprint.add_url_rule(**url) # 註冊到藍圖下 # 註冊藍圖物件到app應用物件中 app.register_blueprint(blueprint,url_prefix="")
上面藍圖註冊到app時, 沒有設定url_prefix路由字首, 接下來我們可以單獨設定一個總路由application/urls.py
,進行路由字首的設定.
在專案預設配置檔案中,application/settings/__init__.py
,新增總路由的配置項
class InitConfig(): """專案預設初始化配置""" # 除錯模式 DEBUG = True # 資料庫相關配置 SQLALCHEMY_DATABASE_URI = "" # 動態追蹤修改設定 SQLALCHEMY_TRACK_MODIFICATIONS = False # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True # Redis REDIS_URL = "" # 設定金鑰,可以通過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字串 SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw" # session儲存配置 # session儲存方式配置 SESSION_TYPE = "redis" # 如果設定session的生命週期是否是會話期, 為True,則關閉瀏覽器session就失效 SESSION_PERMANENT = False # 設定session_id在瀏覽器中的cookie有效期 PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒 # 是否對傳送到瀏覽器上session的cookie值進行加密 SESSION_USE_SIGNER = True # 儲存到redis的session數的名稱字首 SESSION_KEY_PREFIX = "session:" # session儲存資料到redis時啟用的連結物件 SESSION_REDIS = None # 用於連線redis的配置 SESSION_REDIS_HOST = "127.0.0.1" SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 1 # 調整json資料轉換中文的配置 JSON_AS_ASCII=False # 日誌相關配置 LOG_LEVEL = "INFO" # 日誌輸出到檔案中的最低等級 LOG_DIR = "logs/0.log" # 日誌儲存目錄 LOG_MAX_BYTES = 300 * 1024 * 1024 # 單個日誌檔案的儲存上限[單位: b] LOG_BACKPU_COUNT = 20 # 日誌檔案的最大備份數量 LOG_NAME = "flask" # 日誌器的名字 # 藍圖註冊列表 INSTALLED_APPS = [ ] # 總路由 *** URL_PATH = "application.urls"
from application.utils import include urlpatterns = [ include("","home.urls"), ]
from flask import Blueprint from importlib import import_module def path(rule,func_view): # 把藍圖下檢視和路由之間的對映關係處理成字典結構,方便後面註冊藍圖的時候,直接傳參 return {"rule":rule,"view_func":func_view} def include(url_prefix, blueprint_path): """把路由字首和藍圖進行關係對映""" return {"url_prefix":url_prefix,"blueprint_path":blueprint_path} def init_blueprint(app): """自動註冊藍圖""" blueprint_path_list = app.config.get("INSTALLED_APPS") for blueprint_path in blueprint_path_list: blueprint_name = blueprint_path.split(".")[-1] # 自動建立藍圖物件 blueprint = Blueprint(blueprint_name,blueprint_path) # 藍圖自動註冊和繫結檢視和子路由 url_module = import_module(blueprint_path+".urls") # 載入藍圖下的子路由檔案 for url in url_module.urlpatterns: # 遍歷子路由中的所有路由關係 blueprint.add_url_rule(**url) # 註冊到藍圖下 # 讀取總路由檔案 url_path = app.config.get("URL_PATH") urlpatterns = import_module(url_path).urlpatterns # 載入藍圖下的子路由檔案 url_prefix = "" # 藍圖路由字首 for urlpattern in urlpatterns: if urlpattern["blueprint_path"] == blueprint_name+".urls": url_prefix = urlpattern["url_prefix"] break # 註冊藍圖物件到app應用物件中, url_prefix 藍圖的路由字首 app.register_blueprint(blueprint,url_prefix=url_prefix)
4.自動註冊藍圖下的所有模型
1.在藍圖下的models.py中宣告模型,例如:
from application import db class User(db.Model): __tablename__ = "mf_user" id = db.Column(db.Integer, primary_key=True, comment="主鍵ID") name = db.Column(db.String(255), unique=True, comment="賬戶名") password = db.Column(db.String(255), comment="登入密碼") ip_address = db.Column(db.String(255), index=True, comment="登入IP") def __repr__(self): return self.name
2.然後在終端下執行資料遷移
cd ../.. python manage.py db init python manage.py db migrate -m "text"
3.上面的命令執行以後, 我們可以發現模型根本被flask進行識別到.所以我們需要把模型註冊到flask專案中.
from flask import Blueprint from importlib import import_module def path(rule,func_view): # 把藍圖下檢視和路由之間的對映關係處理成字典結構,方便後面註冊藍圖的時候,直接傳參 return {"rule":rule,"view_func":func_view} def include(url_prefix, blueprint_path): """把路由字首和藍圖進行關係對映""" return {"url_prefix":url_prefix,"blueprint_path":blueprint_path} def init_blueprint(app): """自動註冊藍圖""" blueprint_path_list = app.config.get("INSTALLED_APPS") for blueprint_path in blueprint_path_list: blueprint_name = blueprint_path.split(".")[-1] # 自動建立藍圖物件 blueprint = Blueprint(blueprint_name,blueprint_path) # 藍圖自動註冊和繫結檢視和子路由 url_module = import_module(blueprint_path+".urls") # 載入藍圖下的子路由檔案 for url in url_module.urlpatterns: # 遍歷子路由中的所有路由關係 blueprint.add_url_rule(**url) # 註冊到藍圖下 # 讀取總路由檔案 url_path = app.config.get("URL_PATH") urlpatterns = import_module(url_path).urlpatterns # 載入藍圖下的子路由檔案 url_prefix = "" # 藍圖路由字首 for urlpattern in urlpatterns: if urlpattern["blueprint_path"] == blueprint_name+".urls": url_prefix = urlpattern["url_prefix"] break # 註冊模型 *** import_module(blueprint_path+".models") # 註冊藍圖物件到app應用物件中, url_prefix 藍圖的路由字首 app.register_blueprint(blueprint,url_prefix=url_prefix)
專案能自動載入總路由和藍圖路由以後的專案目錄結構,如下:
專案根目錄/ ├── application/ # 專案主要邏輯程式碼儲存目錄 | ├── settings/ # 專案配置儲存目錄 │ │ ├ __init__.py # 專案預設初始化配置檔案 │ │ ├ dev.py # 開發階段的配置檔案 │ │ └ prod.py # 生產階段的配置檔案 │ ├── __init__.py # 專案初始化全域性引導檔案 | ├── utils/ # 專案工具類庫目錄 │ │ ├ commands.py # 自定義命令和載入命令的相關函式 │ │ ├ config.py # 專案配置載入的輔助函式 │ │ ├ session.py # 專案儲存session相關的函式 │ │ └ logger.py # 日誌模組 │ ├── apps/ # 儲存專案中所有藍圖的儲存目錄 │ │ ├── home # 藍圖目錄【這裡是舉例而已】 │ │ │ ├── __init__.py # 藍圖的初始化檔案 │ │ │ ├── urls.py # 藍圖的子路由檔案 │ │ │ ├── models.py # 藍圖的模型檔案 │ │ │ └── views.py # 藍圖的檢視檔案 │ │ ├── __init__.py │ └── urls.py # 總路由 ├── manage.py # 專案的終端管理指令碼檔案