1. 程式人生 > >flask web開發(四)--大型程式的結構

flask web開發(四)--大型程式的結構

|-flasky
	|-app/ #四個頂級資料夾之一,flask程式儲存在這個裡面
		|-templates/
		|-static/
		|-main/
			|-__init__.py
			|-errors.py
			|-forms.py
			|-views.py #這是程式的路由
		|__init__.py
		|-email.py
		|-models.py #資料庫模型
	|-migrations/ #四個頂級資料夾之一,包含資料庫遷移指令碼
	|-tests/ #四個頂級資料夾之一,單元測試編寫在這個包中
		|-__init__.py
		|-test*.py
	|-venv/ #四個頂級資料夾之一,包含python flask的虛擬環境
	|-requirements.txt #列出了所有依賴包,其他電腦中能生成相同的虛擬環境
	|-config.py #儲存了配置資訊
	|-manage.py #用於啟動程式和其他的程式任務,這個指令碼先建立程式,然後定義了配置

在大型的程式結構裡面,我們不像在單一指令碼中使用簡單的字典狀結構配置,而是使用層次結構的配置類:

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config:   #這是基類,包含了通用設定
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME') #這裡不像單一腳本里面使用app.config['MAIL_USERNAME']=...這樣的字典結構
    ...
    @staticmethod
    def init_app(app):  #這個的引數是程式例項,在這個方法中,可以執行對當前環境的配置初始化。
        pass
class DevelopmentConfig(Config): #三個子類之一
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
class TestingConfig(Config):  #三個子類之一
    TESTING = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
        'sqlite://'
class ProductionConfig(Config):  #三個子類之一
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data.sqlite')

config = {        #為四種模式分別指定一個配置類
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

基類config包含了通用的配置,子類分別定義了專用的配置,還可以繼續新增其他的配置類。
在上面設定的三個子類中,SQLALCHEMY_DATABASE_URI 變數分別制定了不同的值,這樣的目的是在每個環境中使用不同的資料庫。


app資料夾中 __init__.py 是程式包的構造檔案

構造檔案匯入大多數正在使用的flask拓展,裡面主要是放置:

from flask_sqlalchemy import SQLAlchemy  #引入拓展
app = Flask(__name__)
app.config.from_object('app.config.DevelopmentConfig') #引入配置
db = SQLAlchemy(app)

我們學習使用工廠函式,延遲建立程式例項,把建立過程移到可顯式呼叫的工廠函式中,這種方法不僅可以給指令碼留出配置程式的時間,還能夠建立多個程式例項。

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from config import config

bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()


def create_app(config_name): #程式的工廠函式,一個引數,程式使用的配置名
    app = Flask(__name__)
    app.config.from_object(config[config_name]) #使用配置物件提供的方法直接從配置檔案裡面匯入配置
    config[config_name].init_app(app)

    bootstrap.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)

    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)   #藍本

    return app

在藍本中實現程式的功能:
上面程式碼的註釋中可以看到藍本,現在程式在執行的時候才會建立,執行之後再使用app.route()定義路由就太晚了,所以使用藍本
藍本和程式類似,可以定義路由,但是在藍本中定義路由是休眠狀態,直到藍本註冊到程式上,路由才會真正生效。
建立藍本的方法:

from flask import Blueprint
main = Blueprint('main', __name__)  #例項化一個藍本物件可以建立藍本
#第一個引數是藍本的名字,所以這個藍本叫做main
#第二個引數是藍本所在的包或者模組,大多數情況下使用__name__
from . import views, errors #view.py中儲存的是路由,所以這樣就把路由和藍本關聯了起來

藍本已經建立完畢,但是還需要將藍本註冊到程式上:
app.regisiter_blueprint(main_blueprint)


需求檔案: requirements.txt

用於記錄所有依賴包以及其精確的版本號
pip可以自動生成這個檔案:
pip freeze >requirements.txt
如果要建立這個虛擬環境的完全副本,可以安裝檔案內的依賴包建立一個新的虛擬環境:
pip install -r requirements.txt