iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
自我挑戰組

月光下的Flask之旅系列 第 12

Day 12 Flask 基本設定

開始專案前需要先對 Flask 設定一下,讓它能夠開發的更順手(又是一段超短的開頭)。

基本設定

剛剛在啟動 server 時使用到了 set 這個指令,set 其實是設定環境變數的指令,flask run 這行是使用了 flask-cli,讓 flask 自動去抓環境變數來設定並執行。不過如果現在有一堆東西要設定,一行一行慢慢寫入也太花時間,而且有時候不小心忘記設定過了什麼又要在茫茫大海中尋找,非常花時間。所以現在就要來講一下如何設定並且開始一個 flask 時有什麼要設定的。

flask 中可設定的值大概有這些 Builtin Configuration Value

首先,讓 flask 運行起來的方式有兩種,透過 flask-cli 或透過 python 來啟動。

flask-cli 啟動

先來說透過 flask-cli 啟動要如何設定:

flask-cli 可以抓環境變數來載入設定後執行,但是一行一行寫入不方便管理,那怎麼辦呢?

你可以透過 .env 檔或是 .flaskenv 檔(這兩個檔案的寫法都跟 Day 09 的 .env 檔一樣,啊記得放在專案根目錄)來統一管理設定,並且 flask-cli 會自動將 這兩個檔案載入到設定後才執行。

而 flask-cli 下指令的時候也可以加上參數。那這三個同時下不同指令的時候會發生什麼事呢(正常不會這樣做,我只是舉例而已)?

由於載入的順序大概是這樣 .flaskenv => .env => CLI-settings(J個是尛?flask run 這個東西,flask run --help 就可以看到怎麼使用了。再說一次,用虛擬環境的要進入虛擬環境喔),所以在後面載入的 .env 會覆蓋掉 .flaskenv 的值;更後面的 CLI-settings 又會覆蓋掉 .env 的值,大概就這樣。

.env.flaskenv 這兩個檔案較適用於不適合公開的設定,例如之後會講到的 SECRET_KEY,那麼透過 python 啟動呢?

python 啟動

python 啟動其實就只是 python app.py 這樣而已。要執行前必須把剛剛註解的那兩行加進來,不然不會執行。

那這樣做有什麼差别呢?

這個方式可以用很多其他的方式來載入設定後再執行(不過這邊的方法都在 flask-cli 啟動時都是在執行後才會載入,這樣就沒有意義了),甚至做到只改一行就改變所有設定;不過 .env.flaskenv 就不行了(雖然 .env 可以另外透過 python-dotnev 這個模組的 load_dotenv() 這個方式額外載入)。

到底又有什麼方式可以載入設定呢?先說比較簡單的:

["<name>"]

這應該是最簡單的,因為 Flask 的 config 其實就是一個 dict (字典,Day 03 有講到),要改寫這個 dict 就直接抓它的 key 改 value 就行了。像這樣:

from flask import Flask


app = Flask(__name__)
app.config["ENV"] = "development"
app.config["DEBUG"] = True


@ app.route("/")
def index():
    return "Hello World"


if __name__ == "__main__":
    app.run()

再把它 run 起來

# 再提醒一次,有用虛擬環境的要進去虛擬環境
$ pipenv shell

$ python app.py

應該可以看到 Environment 變成 development 以及 Debug 變成 on 了!

update

這個方式跟第一個方式其實差不多,都是基於 dict 去操作的,但是不用一個一個改,只要寫好一次 update 就可以了。大概像這樣:

from flask import Flask

CONFIGS = {
    "ENV": "development",
    "DEBUG": True
}

app = Flask(__name__)
app.config.update(CONFIGS)


@ app.route("/")
def index():
    return "Hello World"


if __name__ == "__main__":
    app.run()

# 進入虛擬環境
$ pipenv shell

$ python app.py

因為我都讓它們做同樣事情,結果不會不一樣(有不一樣就是你弄錯了),所以我就懶得放塗了。

from_mapping

第三個方式跟第二個差不多,不過不再基於 dict 去操作,使用的是 flask 提供的方式。像這樣:

from flask import Flask

CONFIGS = {
    "ENV": "development",
    "DEBUG": True
}

app = Flask(__name__)
app.config.from_mapping(CONFIGS)


@ app.route("/")
def index():
    return "Hello World"


if __name__ == "__main__":
    app.run()

# 進入虛擬環境
$ pipenv shell

$ python app.py

對,結果應該又是一樣的。

from_pyfile

這個方式開始就有點不同了,是引入一個檔案(不需要 import,直接輸入檔名),需要新增一個檔案。結構長這樣:

ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock

configs.py

ENV = 'development'
DEBUG = True

app.py

from flask import Flask


app = Flask(__name__)
app.config.from_pyfile('configs.py')


@ app.route("/")
def index():
    return "Hello World"


if __name__ == "__main__":
    app.run()

# 進入虛擬環境
$ pipenv shell

$ python app.py

對啦,結果又双是一樣的。

from_envvar

這個方式跟前一個差不多,但是需要新增環境變數,然後從環境變數中抓到該去哪裡找設定檔。像這樣:

ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock

configs.py

ENV = 'development'
DEBUG = True

app.py

from flask import Flask


app = Flask(__name__)
app.config.from_envvar('FLASK_SETTINGS')


@ app.route("/")
def index():
    return "Hello World"


if __name__ == "__main__":
    app.run()

# 進入虛擬環境
$ pipenv shell

# 設定環境變數
$ set FLASK_SETTINGS=./configs.py
# 執行
$ python app.py

對啦,結果又双叒是一樣的。

from_object (推薦)

這個方式是我比較喜歡的,因為可以同時存放多種設定,例如開發環境設定、部署環境設定等,不用有一堆設定檔,也不需要使用到環境變數,也支援多種方式。像這樣:

ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
  1. 導入後套用設定

    configs.py

    ENV = 'development'
    DEBUG = True
    

    app.py

    from flask import Flask
    import configs as CONFIGS
    
    
    app = Flask(__name__)
    app.config.from_object(CONFIGS)
    
    
    @ app.route("/")
    def index():
        return "Hello World"
    
    
    if __name__ == "__main__":
        app.run()
    

     # 進入虛擬環境
     $ pipenv shell
    
     $ python app.py
    
  2. 直接呼叫模組名稱

    configs.py

    ENV = 'development'
    DEBUG = True
    

    app.py

    from flask import Flask
    
    
    app = Flask(__name__)
    app.config.from_object("configs")
    
    
    @ app.route("/")
    def index():
        return "Hello World"
    
    
    if __name__ == "__main__":
        app.run()
    

     # 進入虛擬環境
     $ pipenv shell
    
     $ python app.py
    
  3. 物件化多設定檔

    configs.py

    class Config:
        TESTING = False
    
    
    class ProductionConfig(Config):
        FLASK_ENV = 'production'
        DEBUG = False
    
    
    class DevelopmentConfig(Config):
        ENV = 'development'
        DEBUG = True
    
    
    class TestingConfig(Config):
        TESTING = True
    

    app.py

    from flask import Flask
    import configs
    
    
    app = Flask(__name__)
    app.config.from_object(configs.DevelopmentConfig)
    
    
    @ app.route("/")
    def index():
        return "Hello World"
    
    
    if __name__ == "__main__":
        app.run()
    

     # 進入虛擬環境
     $ pipenv shell
    
     $ python app.py
    

對啦,結果又双叒叕是一樣的。

最後,app.run() 也是可以加參數的,參考 run()

那麼就大概這樣,本來想說設定只有一點點的,可是沒想到也這麼多。

大家掰~掰~


上一篇
Day 11 Flask 快速開始
下一篇
Day 13 Flask Route
系列文
月光下的Flask之旅30

尚未有邦友留言

立即登入留言