我們將介紹一種使用包和模組組織大型程式的方式。
flask 程式的基本結構如示例 7-1 所示。
這種結構有4個頂級資料夾:
2) migrations資料夾包含資料庫遷移指令碼
3)單元測試編寫在tests包中
4)venv資料夾包含python虛擬環境
同時還建立了一些新檔案:
程式經常需要設定多個配置。
使用層次結構的配置類。
#config.py:程式的配置
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class config:
secret_key = os.environ.get('secret_key') or 'hard to guess string'
sqlalchemy_commit_on_teardown = true
flasky_mail_subject_prefix = '[flasky]'
flasky_mail_sender = 'flasky admin '
flasky_admin = os.environ.get('flasky_admin')
@staticmethod
pass
class developmentconfig(config):
debug = true
mail_server = 'smtp.googlemail.com'
mail_port = 587
mail_use_tls = true
mail_username = os.environ.get('mail_username')
mail_password = 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:///' + os.path.join(base.dir, 'data-test.sqlite')
class productionconfig(config):
sqlalchemy_database_uri = os.environ.get('database_url') or 'sqlite:///' + os.path.join(base.dir, 'data.sqlite')
config =
基類config中包含通用配置,子類分別定義專用的配置。
secret_key從環境變數中匯入,這樣配置方式更靈活且更安全。
在3個子類中,sqlalchemy_database_uri變數都指定了不同的值,這樣程式就可在不同的環境中執行,每個環境使用不同的資料庫。
config字典中註冊了不同的配置環境,而且還註冊了乙個預設配置。
程式包(可改用程式專用名字)用來儲存程式的所有**、模板和靜態檔案。
在單個檔案中開發程式時,有個很大的缺點,因為程式在全域性作用域中建立,所以無法動態修改配置。
這個問題的解決方法是延遲建立程式例項,把建立過程移到可顯示呼叫的工廠函式中。
from flask import flask, render_template
from flask.ext.bootstrap import bootstrap
from flask.ext.mail import mail
from flask.ext.moment import moment
from flask.ext.sqlalchemy import sqlalchemy
from config import config
bootstrap = bootstrap()
mail = mail()
moment = moment()
db = sqlalchemy()
# 附加路由和自定義的錯誤頁面
工廠函式返回建立的程式例項,現在的工廠函式還缺少路由和自定義的錯誤頁面處理程式。
為了獲得最大的靈活性,程式建立了乙個包,用於儲存藍本。
from flask import blueprint
main = blueprint('main', __name__)#例項化乙個blueprint類物件來建立藍本
from . import views, errors
blueprint類有兩個必須制定的引數:藍本的名字和藍本所在的包或模組。和程式一樣,大多數情況下第二個引數使用python的__name__變數即可。
#...
from .main import main as main_blueprint
錯誤處理程式如下:
from flask import render_template
from . import main
def page_not_found(e)
return render_template(404.html), 404
def internal_server_error(e):
return render_template('500.html'), 500
藍本中的程式路由如下:
from datetime import datetime
from flask import render_template, session, redirect, url_for
from . import main]
from ./forms import nameform
form .. import db
from ../models import user
@main.route('/', methods=['get', 'post'])
def index():
form = nameform()
if form.validate_on_submit():
#....
return redirect(url_for('./index'))
return render_template('index.html', form=form, name=session.get('name'), known=session.get('known', false), current_time=datetime.utcnow())
在藍本中編寫檢視函式有兩點不同:第一,路由修飾器由藍本提供;第二,url_for()函式的用法不同。在普通檔案中,url_for()函式的第乙個引數是路由的端點名,在程式的路由中,預設為檢視函式的名字。
而在藍本中,flask會為藍本中的全部端點加上乙個命名空間,這樣就可以在不同的藍本中使用相同的端點名定義檢視函式,而不會產生衝突。命名空間就是藍本的名字,即blueprint建構函式的第乙個引數。所以使用url_for("main.index"),在藍本中可以簡寫省略藍本名,例如url_for('.index')。
頂級資料夾中的manage.py檔案用於啟動程式。
#manage.py:啟動指令碼
#!/usr/bin/env python
import os
from flask.ext.script import manager, shell
from flask.ext.migrate import migrate, migratecommand
def make_shell_context():
manager.add_command('shell', shell(make_context = make_shell_context))
manager.add_command('db', migratecommand)
if __name__=='__main__':
manager.run()
程式中必須包含乙個requirements.txt檔案,用於記錄所有依賴包及其精確地版本號。
pip freeze>requirements.txt
編寫兩個簡單的測試。
#tests/test_basics.py:單元測試
import unittest
class basicstestcase(unittest.testcase):
def setup(self):
db.create_all()
def teardown(self):
db.session.remove()
db.drop_all()
這個測試使用 python 標準庫中的 unittest 包編寫。 setup() 和 teardown() 方法分別在各測試前後執行,並且名字以 test_ 開頭的函式都作為測試執行。 Flask從入門到精通之大型程式的結構二
在單個檔案中開發程式很方便,但卻有個很大的缺點,因為程式在全域性作用域中建立,所以無法動態修改配置。執行指令碼時,程式例項已經建立,再修改配置為時已晚。這一點對單元測試尤其重要,因為有時為了提高測試覆蓋度,必須在不同的配置環境中執行程式。from flask import flask from fl...
Flask學習筆記
web 發展至今,特別是伺服器端,涉及到的知識 內容,非常廣泛。這對程式設計師的要求會越來越高。如果採用成熟,穩健的框架,那麼一些基礎的工作,比如,網路操作 資料庫訪問 會話管理等都可以讓框架來處理,那麼程式開發人員可以把精力放在具體的業務邏輯上面。使用web框架開發web應用程式可以降低開發難度,...
Flask 學習筆記
因為mac自帶了python2.7,所以這個文章是基於2.7版本的 依賴於兩個外部庫 werkzeug和jinjia2.werkzeug是乙個wsgi工具集,jinjia2負責渲染模版 2.安裝 1 mac osx或linux sudo pip install virtualenv mkdir my...