當(dāng)你學(xué)習(xí) Flask 的時(shí)候,配置看起來(lái)很簡(jiǎn)單躬它。你只要在 config.py 中定義一些變量接著一切就能工作了秸应。當(dāng)你開(kāi)始必須要管理生產(chǎn)應(yīng)用的配置的時(shí)候软啼,這些簡(jiǎn)單性開(kāi)始消失了祸挪。你可能需要保護(hù) API 密鑰以及為不同的環(huán)境使用不同的配置(例如,開(kāi)發(fā)和生產(chǎn)環(huán)境)雹仿。在本章節(jié)中我們會(huì)介紹 Flask 一些先進(jìn)的功能胧辽,它可以使得管理配置容易些公黑。
簡(jiǎn)單的例子
一個(gè)簡(jiǎn)單的應(yīng)用程序可能不會(huì)需要任何這些復(fù)雜的功能凡蚜。你可能只需要把 config.py 放在你的倉(cāng)庫(kù)/版本庫(kù)的根目錄并且在 app.py 或者 yourapp/\\init\\.py 中加載它朝蜘。
config.py 文件中應(yīng)該每行包含一個(gè)配置變量賦值。當(dāng)你的應(yīng)用程序初始化的時(shí)候暇仲,在 config.py 中的配置變量用于配置 Flask 和它的擴(kuò)展并且它們能夠通過(guò) app.config 字典訪問(wèn)到 – 例如熔吗,app.config["DEBUG"]。
DEBUG = True # Turns on debugging features in Flask
BCRYPT_LEVEL = 12 # Configuration for the Flask-Bcrypt extension
MAIL_FROM_EMAIL = "robert@example.com" # For use in application emails
配置的變量可以被 Flask讼载,它的擴(kuò)展或者你來(lái)使用中跌。這個(gè)例子中漩符, 每當(dāng)我們?cè)谝环馐聞?wù)性郵件中需要默認(rèn)的 “發(fā)件人” 的時(shí)候嗜暴,我們可以使用 app.config["MAIL_FROM_EMAIL"] – 例如闷沥,密碼重置舆逃。把這些信息放置于一個(gè)配置變量中使得以后能夠容易地修改它路狮。
# app.py or app/__init__.py
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
# Now we can access the configuration variables via app.config["VAR_NAME"].
- DEBUG: 為你提供了調(diào)試錯(cuò)誤的一些方便的工具蔚约。 這包括一個(gè)基于 Web 的堆棧跟蹤和交互式的 Python 控制臺(tái)砸抛。在開(kāi)發(fā)環(huán)境中設(shè)置成 True苔咪; 生產(chǎn)環(huán)境中設(shè)置成 False团赏。
- SECRET\_KEY:這是 Flask 用來(lái)為 cookies 簽名的密鑰。 它也能被像 Flask-Bcrypt 類(lèi)的擴(kuò)展使用丝里。 你應(yīng)該在你的實(shí)例文件夾中定義它杯聚, 這樣可以遠(yuǎn)離版本控制幌绍。 你可以在下一個(gè)章節(jié)中閱讀更多關(guān)于示例文件夾的內(nèi)容傀广。一般情況下這應(yīng)該是一個(gè)復(fù)雜的隨機(jī)值。
- BCRYPT\_LEVEL:如果你使用 Flask-Bcrypt 來(lái)散列用戶密碼的話伪冰, 你需要指定一個(gè)“循環(huán)”數(shù)贮聂,這個(gè)數(shù)是在執(zhí)行散列密碼的 算法需要的。如果你不使用 Flask-Bcrypt歼冰,你可以 忽略這里停巷。用于散列密碼的循環(huán)數(shù)越大畔勤,攻擊者猜測(cè)密碼 的時(shí)間會(huì)越長(zhǎng)庆揪。同時(shí)缸榛,循環(huán)數(shù)越大會(huì)增加散列密碼的時(shí)間内颗。后面我們會(huì)給出在 Flask 應(yīng)用中 使用 Bcrypt 的一些最佳實(shí)踐均澳。
<strong>
確保在生產(chǎn)環(huán)境中 DEBUG 設(shè)置成 False找前。如果保留 DEBUG 為 True躺盛,它允許用戶在你的服務(wù)器上執(zhí)行任意的 Python槽惫。
</strong>
實(shí)例文件夾
有時(shí)候你需要定義包含敏感信息的配置變量躯枢。我們想要從 config.py 中分離這些變量并且讓它們保留在倉(cāng)庫(kù)/版本庫(kù)之外槐臀。你可能會(huì)隱藏像數(shù)據(jù)庫(kù)密碼以及 API 密鑰的一些敏感信息水慨,或者定義于特定于指定機(jī)器的配置變量。為讓實(shí)現(xiàn)這些要求更加容易些朝抖,F(xiàn)lask 提供了一個(gè)叫做 instance folders 的功能治宣。實(shí)例文件夾是倉(cāng)庫(kù)/版本庫(kù)下的一個(gè)子目錄并且包含專(zhuān)門(mén)為這個(gè)應(yīng)用程序的實(shí)例的一個(gè)配置文件侮邀。我們不希望它提交到版本控制绊茧。
config.py
requirements.txt
run.py
instance/
config.py
yourapp/
__init__.py
models.py
views.py
templates/
static/
使用實(shí)例文件夾
我們使用 app.config.from_pyfile()
來(lái)從一個(gè)實(shí)例文件夾中加載配置變量华畏。當(dāng)我們調(diào)用 Flask()
來(lái)創(chuàng)建我們的應(yīng)用的時(shí)候亡笑,如果我們?cè)O(shè)置了 instance_relative_config=True
仑乌, app.config.from_pyfile()
將會(huì)從 instance/
目錄加載指定文件叶撒。
# app.py or app/__init__.py
app = Flask(__name__, instance_relative_config=True)
app.config.from_object('config')
app.config.from_pyfile('config.py')
現(xiàn)在我們可以像在 config.py
中那樣在 instance/config.py
中定義配置變量绝骚。你也應(yīng)該把你的實(shí)例文件夾加入到版本控制系統(tǒng)的忽略列表中。要使用 Git
做到這一點(diǎn)的話祠够,你需要在 .gitignore
新的一行中添加 instance/
压汪。
密鑰
實(shí)例文件夾的隱私性成為在其里面定義不想暴露到版本控制的密鑰的最佳候選。這些密鑰可能包含了你的應(yīng)用的密鑰或者第三方 API 密鑰古瓤。如果你的應(yīng)用是開(kāi)源的或者以后可能會(huì)公開(kāi)的話止剖,這一點(diǎn)特別重要腺阳。我們通常要求其他用戶或者貢獻(xiàn)者使用自己的密鑰。
# instance/config.py
SECRET_KEY = 'Sm9obiBTY2hyb20ga2lja3MgYXNz'
STRIPE_API_KEY = 'SmFjb2IgS2FwbGFuLU1vc3MgaXMgYSBoZXJv'
SQLALCHEMY_DATABASE_URI= \\
"postgresql://user:TWljaGHFgiBCYXJ0b3N6a2lld2ljeiEh@localhost/databasename"
基于環(huán)境的配置
如果在你的生產(chǎn)環(huán)境和開(kāi)發(fā)環(huán)境中的差異非常小的話穿香,你可能想要使用實(shí)例文件夾來(lái)處理配置的變化亭引。定義在 'instance/config.py' 文件中的配置變量能夠覆蓋 'config.py' 中的值。你只需要在 'app.config.from_object()' 后調(diào)用 'app.config.from_pyfile()'皮获。這樣用法的好處之一就是在不同的機(jī)器上修改你的應(yīng)用的配置雁歌。
# config.py
DEBUG = False
SQLALCHEMY_ECHO = False
# instance/config.py
DEBUG = True
SQLALCHEMY_ECHO = True
在生產(chǎn)環(huán)境上,我們略去上面 'instance/-config.py' 中的配置變量佳窑,它會(huì)退回到定義在 'config.py' 中的值耙厚。
<em> 了解更多關(guān)于 Flask-SQLAlchemy 的 配置項(xiàng)呆细。(中文版的位于:http://www.pythondoc.com/flask-sqlalchemy/config.html#configuration-keys)</em>
基于環(huán)境變量配置
實(shí)例文件夾不應(yīng)該出現(xiàn)在版本控制中。這就意味著你將無(wú)法跟蹤你的實(shí)例配置的變化。如果只是一指巡、兩個(gè)變量這可能不是什么問(wèn)題狸吞,但是如果你在不同的環(huán)境上(生產(chǎn)暖侨,預(yù)升級(jí)宅广,開(kāi)發(fā),等等)配置都有些微調(diào)話,你就不會(huì)想要存在丟失它們的風(fēng)險(xiǎn)扛门。
Flask 給我們選擇配置文件的能力葬凳,它可以基于一個(gè)環(huán)境變量的值來(lái)加載不同的配置文件荐健。這就意味著在我們的倉(cāng)庫(kù)/版本庫(kù)里,我們可以有多個(gè)配置文件并且總會(huì)加載正確的那一個(gè)。一旦我們有多個(gè)配置文件的話,我可以把它們移入它們自己 config 文件夾中权均。
requirements.txt
run.py
config/
__init__.py # Empty, just here to tell Python that it's a package.
default.py
production.py
development.py
staging.py
instance/
config.py
yourapp/
__init__.py
models.py
views.py
static/
templates/
在上面的文件列表中我們有多個(gè)不同的配置文件囊咏。
- config/default.py: 默認(rèn)的配置值炮捧,可用于所有的環(huán)境或者被個(gè)人的環(huán)境給覆蓋书蚪。
- config/development.py: 用于開(kāi)發(fā)環(huán)境的配置值。這里你可能會(huì)指定本地?cái)?shù)據(jù)庫(kù)的 URI。
- config/production.py: 用于生產(chǎn)環(huán)境的配置值莲祸。在這里 DEBUG 一定要設(shè)置成 False。
- config/staging.py: 根據(jù)開(kāi)發(fā)進(jìn)度语泽,你可能會(huì)有一個(gè)模擬生產(chǎn)環(huán)境绳锅,這個(gè)文件主要用于這種場(chǎng)景。
為了決定要加載哪個(gè)配置文件剃幌,我們會(huì)調(diào)用 'app.config.from_envvar()'。
# yourapp/\\_\\_init\\_\\_.py
app = Flask(__name__, instance_relative_config=True)
# Load the default configuration
app.config.from_object('config.default')
# Load the configuration from the instance folder
app.config.from_pyfile('config.py')
# Load the file specified by the APP\\_CONFIG\\_FILE environment variable
# Variables defined here will override those in the default configuration
app.config.from_envvar('APP_CONFIG_FILE')
環(huán)境變量的值應(yīng)該是配置文件的絕對(duì)路徑。
我們?nèi)绾卧O(shè)置這個(gè)環(huán)境變量取決于我們運(yùn)行應(yīng)用所在的平臺(tái)晨汹。如果我們運(yùn)行在一個(gè)普通的 Linux 服務(wù)器上曙聂,我們可以編寫(xiě)一個(gè)設(shè)置環(huán)境變量的 shell 腳本并且運(yùn)行 run.py庐氮。
# start.sh
APP\\_CONFIG\\_FILE=/var/www/yourapp/config/production.py
python run.py
start.sh 對(duì)于每一個(gè)環(huán)境都是獨(dú)一無(wú)二的寸士,因此它應(yīng)該被排除在版本控制之外凡人。在 Heroku 上,我們需要使用 Heroku 工具來(lái)設(shè)置環(huán)境變量。這種設(shè)置方式也適用于其它的 PaaS 平臺(tái)兴使。
摘要
- 一個(gè)簡(jiǎn)單的應(yīng)用程序可能僅僅需要一個(gè)配置文件:config.py。
- 實(shí)例文件夾能夠幫助我們隱藏敏感的配置值苹粟。
- 實(shí)例文件夾能夠用于針對(duì)每個(gè)特定的環(huán)境需要改變應(yīng)用程序的配置的場(chǎng)景嵌削。
- 我們應(yīng)該在一些復(fù)雜的以及多個(gè)的環(huán)境中使用環(huán)境變量以及 'app.config.from_envvar()' 。