day98:MoFang:服務端項目搭建

目錄

1.準備工做python

2.建立項目啓動文件manage.pymysql

3.構建全局初始化函數並在函數內建立app應用對象redis

4.經過終端腳本啓動項目sql

5.項目加載配置數據庫

6.數據庫初始化json

  1.SQLAlchemy初始化flask

  2.Redis初始化api

  3.session存儲到redis數據庫中瀏覽器

  4.數據遷移初始化緩存

7.日誌初始化

8.藍圖初始化

  1.經過終端命令建立藍圖,並在藍圖中生成view/model/url等文件

  2.將藍圖註冊到APP應用對象下

  3.註冊路由和視圖之間的關係

  4.自動註冊藍圖下的全部模型

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.構建全局初始化函數並在函數內建立app應用對象

1.把引導整個項目啓動的全局初始化代碼,保存到application/__init__py,代碼:

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.經過終端腳本啓動項目

applicatiion/__init__py,代碼:

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

2.編寫項目默認配置文件, application/settings/__init__.py代碼:

class InitConfig():
    """項目默認初始化配置"""
    DEBUG = True

固然, 項目開發過程完成之後確定會項目上線,因此針對配置文件,咱們能夠準備不一樣環境下的配置

application/settings/dev.py,代碼:

from . import InitConfig
class Config(InitConfig):
    """項目開發環境下的配置"""
    DEBUG = True

application/settings/prod.py,代碼:

from . import InitConfig
class Config(InitConfig):
    """項目運營環境下的配置"""
    DEBUG = False

3.在項目引導文件application/__init__py中加載配置,代碼:

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初始化

1.默認項目配置文件中增長配置選項,application/settings/__init__.py,代碼:

class InitConfig():
    """項目默認初始化配置"""
    # 調試模式
    DEBUG = True

    # 數據庫相關配置
    SQLALCHEMY_DATABASE_URI = ""
    # 動態追蹤修改設置
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO= True

2.開發配置dev.py中,配置數據庫鏈接信息,代碼:

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;

4.在項目全局引導文件中,對數據庫功能進行初始化,application/__init__.py,代碼:

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初始化

1.默認配置文件,application/settings/__init__py,代碼:

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"

2.在全局引導文件中, 對redis進行初始化,applicaiton/__init__.py,代碼:

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數據庫中

1.由於須要單獨設置一個數據庫存放session,因此咱們再次單獨配置一個關於session加載配置的函數init_session,

application/utils/session.py,代碼:

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)

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 = 0

3.在本地開發配置中,設置session存儲指定的redis庫中,application/settings/dev.py,代碼:

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

4.在項目全局引導文件application/__init__.py中對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.數據遷移初始化

1.項目全局引導文件application/__init__py,代碼:

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.構建日誌模塊

1.把日誌初始化相關的代碼封裝成一個函數,application/utils/logger.py,代碼:

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"             # 日誌器的名字

3.開發環境配置文件dev.py中配置具體的日誌相關信息,代碼:

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"                    # 日誌器名稱

4.在 application/__init__.py文件中的init_app 方法中調用日誌初始化。

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等文件

1.在application下建立apps目錄,apps之後專門用於保存每個項目的藍圖,並在apps建立home藍圖目錄,並在__init__.py文件中建立藍圖對象

經過自定義終端命令, 建立一個自動生成藍圖目錄的命令.application/utils/commands.py,代碼:

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)

2.上面的命令就能夠幫咱們完成項目中生成藍圖的功能,接下來咱們就能夠直接把命令註冊到manage對象中就能夠使用了.

可是, 咱們日後的開發中確定還會繼續的須要進行自定義終端命令,因此咱們聲明一個load_command的函數,讓自動幫咱們完成加載註冊自定義終端命令的過程.

application/utils/commands.py,代碼:

 

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)

3.在項目全局引導文件application/__init__.py中, 調用load_command函數註冊命令

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

4.接下來就能夠在終端下,經過命令生成藍圖目錄了.

命令:

cd application/apps
python ../../manage.py blue -nhome

效果:

2.將藍圖註冊到APP應用對象下

有了藍圖之後,接下來咱們就能夠視圖代碼,模型代碼,路由代碼等存儲到藍圖目錄下了,可是咱們須要把藍圖註冊到app應用對象下.因此咱們註冊藍圖這塊代碼也能夠封裝到一個函數中.讓程序自動識別並註冊.

項目中能夠有多個藍圖,可是有些藍圖可能並不能提供給客戶端訪問,因此咱們須要在配置文件中聲明一個藍圖註冊列表, 在init_blueprint函數中只註冊配置列表的藍圖

1.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 = [

    ]

application/settings/dev.py,代碼:

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應用對象裏面,

application/utils/__init__.py,代碼:

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="")

3.項目全局引導文件中, 調用init_blueprint方法, 自動註冊藍圖.application/__init__.py,代碼:

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

3.註冊路由和視圖之間的關係

1.註冊子路由和視圖之間的關係

註冊了藍圖對象之後,藍圖下面的視圖方法和視圖對應的路由關係也要進行註冊!

因此, 在藍圖home下面的urls.py文件中,經過path方法把url地址和視圖方法進行處理成字典,而後把字典做爲成員返回到變量urlpatterns列表中.

1.application/utils/__init__.py,生成path函數,代碼:

from flask import Blueprint
from importlib import import_module
def path(rule,func_view):
    # 把藍圖下視圖和路由之間的映射關係處理成字典結構,方便後面註冊藍圖的時候,直接傳參
    return {"rule":rule,"view_func":func_view}

2.在藍圖下的urls.py中,註冊視圖和路由的關係,home/urls.py,代碼:

from . import views
from application.utils import path
urlpatterns = [
    path("/",views.index),
]

視圖代碼:

def index():
    return 'index'

3.在init_blueprint初始化藍圖的函數中, 生成藍圖對象之後自動加載並註冊藍圖和視圖

application/utils/__init__.py,代碼:

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="")

2.註冊總路由和藍圖之間的關係

4.此時, 運行項目,就容許藍圖中視圖經過url地址提供給客戶端訪問了.

上面藍圖註冊到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"

5.建立總路由文件並註冊藍圖和路由前綴的關係, application/urls.py,代碼:

from application.utils import include
urlpatterns = [
    include("","home.urls"),
]

6.接下來,在init_blueprint藍圖初始化函數中新增判斷識別路由前綴的代碼; 同時, 把路由前綴和藍圖映射關係的處理代碼封裝成include方法,方便之後需求變化時能夠直接調整.

application/utils/__init__.py,代碼:

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項目中.

application/utils/__init__.py,代碼:

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               # 項目的終端管理腳本文件
相關文章
相關標籤/搜索