--- title: Flask 基本框架配置 tags: Python description: Python Flask Web與Docker建置網站筆記 --- # Flask 基本框架配置 GitHub: https://github.com/s123600g/FlaskDemoNotes/ 在Flask網站基礎框架上預設會有以下結構: ``` . ├── BaseData │   ├── BaseData.py │   ├── __init__.py │   ├── Config.py ├── DB_initialize.bat ├── DB_initialize.sh ├── Manage.py ├── Server.py ├── Startup.py ├── migrations │   ├── README │   ├── __pycache__ │   │   └── env.cpython-36.pyc │   ├── alembic.ini │   ├── env.py │   ├── script.py.mako │   └── versions │   ├── 8c1ac1a960d2_.py │   └── __pycache__ │   └── 8c1ac1a960d2_.cpython-36.pyc ├── static │   ├── css │   │   └── base.css │   └── js │   └── base.js ├── templates │   └── index.html ├── uwsgi │   └── uwsgi.log └── uwsgi.ini ``` * [Config.py網站整體參數配置](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#Configpy%E7%B6%B2%E7%AB%99%E6%95%B4%E9%AB%94%E5%8F%83%E6%95%B8%E9%85%8D%E7%BD%AE) * [Startup.py啟動初始化](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#Startuppy%E5%95%9F%E5%8B%95%E5%88%9D%E5%A7%8B%E5%8C%96) * [Server.py路由與動作控制中心](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#Serverpy%E8%B7%AF%E7%94%B1%E8%88%87%E5%8B%95%E4%BD%9C%E6%8E%A7%E5%88%B6%E4%B8%AD%E5%BF%83) * [BaseData資料模型](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#BaseData%E8%B3%87%E6%96%99%E6%A8%A1%E5%9E%8B) * [Manage.py執行命令控管](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#Managepy%E5%9F%B7%E8%A1%8C%E5%91%BD%E4%BB%A4%E6%8E%A7%E7%AE%A1) * [uwsgi.ini uWSGi配置檔](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#uWSGi%E9%85%8D%E7%BD%AE%E6%AA%94) * [static靜態檔案目錄](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#%E9%9D%9C%E6%85%8B%E6%AA%94%E6%A1%88%E7%9B%AE%E9%8C%84%E3%80%81HTML%E8%88%87%E6%A8%A1%E6%9D%BF%E7%9B%AE%E9%8C%84) * [templates HTML與模板目錄](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#%E9%9D%9C%E6%85%8B%E6%AA%94%E6%A1%88%E7%9B%AE%E9%8C%84%E3%80%81HTML%E8%88%87%E6%A8%A1%E6%9D%BF%E7%9B%AE%E9%8C%84) * [DB_initialize.bat、DB_initialize.sh 資料模型更新腳本](https://hackmd.io/Yyi0z84aTxuHtL5A21ew_g?both#%E8%B3%87%E6%96%99%E6%A8%A1%E5%9E%8B%E6%9B%B4%E6%96%B0%E8%85%B3%E6%9C%AC) # 快速使用建置 ### Step 1.下載好專案包,放置在自己指定位置。 https://github.com/s123600g/FlaskDemoNotes/tree/master/flask_base_framework 建立完成後請記得在專案目錄內新增一個uwsgi目錄。 ### Step 2.建立好Docker 映像檔。 關於容器建置使用映像檔可參考 [使用Docker建置Nginx結合uWSGI映像檔](https://hackmd.io/CVdNFGTyTqKoMZRwauV2eg?both) ### Step 3.資料模型初始化 資料模型實體檔放置在 **baseData/** 底下,實體檔為 ```BaseData.py```。 範例資料庫使用MySQL,在進行資料模型初始化之前必須要先完成 - [x] 建立資料庫 --> ```flask``` - [x] 建立使用者 --> ```myflask / myflask``` (user / password) - [x] 設定使用者與資料庫之間權限 ```Config.py```內設定好資料庫連接參數 ```python= db_config = { 'db_user': "myflask", # User 'db_psw': "myflask", # User PassWord 'db_host': "127.0.0.1:3307", # DB Host 'db_schema': "flask" # DB Schema Name } ``` db_host為資料庫連接位址,因筆者使用Docker MySQL,在連接port上設置會跟預設3306不一樣。 關於Docker MySQL可參考 https://hub.docker.com/_/mysql 將```DB_initialize.bat```內部參數 **DirPath** ``` script= Set DirPath=E:\Project\GitHub\FlaskDemoNotes\flask_base_framework\ ``` 更改為專案放置位置資訊,在點擊執行即可。 執行前: ![](https://i.imgur.com/hyI85Hq.png) 執行中: ![](https://i.imgur.com/IliVO6s.png) 執行後: ![](https://i.imgur.com/rWDyxCV.png) ### Step 4.運行Docker 容器服務。 關於建立容器服務可參考 [使用Docker運行Nginx與uWSGI容器服務](https://hackmd.io/0VSgSzPHTfaAfwcO3mVZ1Q) 運行語法 ```docker= docker run --name flask_base_framework -p 85:80 -v E:\Project\GitHub\FlaskDemoNotes\flask_base_framework:/web/web_data -d nginx_flask_server ``` 將參數 **-v** 內 ``` E:\Project\GitHub\FlaskDemoNotes\flask_base_framework ``` 換成讀者自己放置的位置即可。 ### Step 5.容器服務執行起來後可在瀏覽器輸入 http://127.0.0.1:85/index ![](https://i.imgur.com/CmaYxop.png) # 配置說明 Config.py網站整體參數配置 -- 重要整體參數配置都會設置在此檔案內,有運作模式、網站模板與靜態檔案目錄、資料庫連接字串、使用者自訂參數...等等。 配置檔內容需要包含下面三個重要類別: 1. BaseConfig 2. DevelopermentConfig 3. ProductionConfig 除了上面三個重要類別之外,其餘開發者也可以在自行增加配置參數區塊。 ### BaseConfig類別內部配置 #### 靜態目錄與模板目錄位置 ```python= static_url_path = '/static' static_folder = 'static' template_folder = 'templates' ``` #### 資料庫連接配置語法參數 相關參考: [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) [Flask-SQLAlchemy Configuration](https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/) [Flask-SQLAlchemy Connection URI Format](https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/#connection-uri-format) [SQLAlchemy ORM Object Relational Tutorial](https://docs.sqlalchemy.org/en/13/orm/tutorial.html) 資料庫連接語法以MySQL為例。 ```python= db_config = { 'db_user': "myflask", 'db_psw': "myflask", 'db_host': "127.0.0.1:3307", 'db_schema': "flask" } SQLALCHEMY_DATABASE_URI = "mysql://{}:{}@{}/{}".format( db_config['db_user'], db_config['db_psw'], db_config['db_host'], db_config['db_schema']) SQLALCHEMY_TRACK_MODIFICATIONS = True SQLAlCHEMY_COMMIT_ON_TEARDOWN = False ``` ### DevelopermentConfig、ProductionConfig類別內部配置 兩者類別是管理網站運作時,運行模式為開發或正式環境,Session Data加密金鑰設置。 各自都繼承上面BaseConfig類別,在網站啟動時選擇哪一種模式運行時,會自動加載我們在BaseConfig類別中基本設置。 **DevelopermentConfig** ```python= class DevelopermentConfig(BaseConfig): DEBUG = True SECRET_KEY = "FLAskOsw12j/3yX R~Xkl!fgN]baseD/,?TT" ``` **ProductionConfig** ```python= class ProductionConfig(BaseConfig): DEBUG = False SECRET_KEY = "flAsK02385m/4eq s~Xkl!fgN]baseP/,?RL" ``` ### DevelopermentConfig、ProductionConfig模式選擇項目清單 這是給網站主體控制中心在初始化啟動時,選擇運作模式來源開關。 ```python= config = { 'developermentConfig': DevelopermentConfig, 'productionConfig': ProductionConfig, 'run_mode_dev':True } ``` **run_mode_dev**管控網站運作是否為開發模式,用在Flask初始化載入封裝模式選擇。 Startup.py啟動初始化 -- Startup.py為網站剛開始啟動時,會先初始化必要運作模組與參數配置載入,例如以下模組 * Flask * Flask-SQLALchemy * Flask Restful-API * Flask-Admin * Flask-Login * Flask-CSRF 都會在此做載入初始化本體動作,後面其他自訂模組要運用時,只要從Startup匯入該模組變數即可。 ```python= from Startup import app ``` ### Flask主體初始載入 建置一個**app**,後面許多控制模組都會用到此變數。 ```python= app = Flask(__name__) ``` 載入網站運作模式(**developermentConfig** / **productionConfig**) ```python= if config['run_mode_dev']: # 載入 Flask Config Setting Values,模式為 developermentConfig app.config.from_object(config['developermentConfig']) else: # 載入 Flask Config Setting Values,模式為 productionConfig app.config.from_object(config['productionConfig']) ``` ### Flask-SQLALchemy資料模組初始載入 建置一個**db**,後面許多控制模組如果要調用資料庫都會用到此變數,在資料模型建立資料表時,也會用到此變數。 ```python= db = SQLAlchemy(app) ``` 註冊資料模型 ```python= from BaseData.BaseData import Base_Data ``` > 如果要建立一個新的資料表時,透過在BaseData內建立好該資料表模型檔後,記得要來此註冊該模型這樣才會被建立起來,如果忘記這一步資料控制模組不會知道有新增一筆資料表模型,自然就不會在資料庫中建立該資料表。 Server.py路由與動作控制中心 -- Server.py為網站運作主要程式,包含了頁面控制項與路由導向處理。 ### 匯入網站主要模組 從Startup匯入主要運作模組變數 ```python= from Startup import app, db ``` ### 匯入建好的資料模型 ```python= from Model import Base_Data ``` 在之後開發如果要在頁面控制項調用**Base_Data**資料表,必須要完成這一步驟才能進行。 ### 頁面控制項配置 開發頁面控制項功能會搭一個路由導向配置 ```python= @app.route("自訂路由", methods=['自訂可接收Http Request Type']) ``` 形成一個完整響應請求處理端,基本頁面網址會配置一個響應請求處理端。 建立一個網址為 **http:localhost:85/index** 響應請求處理端頁面控制項範例。 ```python= @app.route("/index", methods=['GET']) def index(): return render_template('index.html') ``` * 路由設置 ```python= @app.route(自訂網站位置, methods=[設置可接收請求型態]) ``` 範例中建置了一個網站位置為"/index",並且可接收請求型態為'GET' 更詳細說明內容可參考: https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations * 控制項 用Python建立功能函式形式,函式名稱可自訂並且最後會回傳一個Html模板,最後此模板會渲染成我們所看到的網站介面(View)。 完整範例: ```python= # -*- coding: utf-8 -*- from Startup import app, db from flask import render_template ''' ---------------------------------------------------------------------- 匯入資料表模型 ---------------------------------------------------------------------- ''' from BaseData.BaseData import Base_Data '''-------------------------------------------------------------------''' ''' ---------------------------------------------------------------------- 網站頁面-404 Not Found實作區塊 ---------------------------------------------------------------------- ''' @app.errorhandler(404) def page_not_found(e): # 404 Not Found頁面 return 'PageNotFound 404', 404 '''-------------------------------------------------------------------''' ''' ---------------------------------------------------------------------- 頁面-index 實作區塊 ---------------------------------------------------------------------- ''' @app.route("/index", methods=['GET']) def index(): return render_template('index.html') '''-------------------------------------------------------------------''' ``` BaseData資料模型 -- Flask利用物件關聯對映(ORM)方式來進行資料處理,在此之前需要建立資料庫中每個資料表類別,在做資料查詢新增修改上,才能夠用物件形式來對資料表進行操作。 相關參考: [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) [Flask-SQLAlchemy Declaring Models](https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/#simple-example) [SQLAlchemy ORM](https://docs.sqlalchemy.org/en/13/) [SQLAlchemy Declarative](https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/index.html) Flask-SQLAlchemy是Flask預設封裝基本SQLAlchemy使用模組,其內容功能都與SQLAlchemy ORM是一樣的,在Flask-SQLAlchemy官方說明也有提到SQLAlchemy ORM。 建置模型套件來源筆者使用SQLAlchemy ORM,在運作上都相容能夠使用。 在官方預設教學上,會看到是使用一個Model.py來放置資料表類別模型,如果在此筆記框架下,內容類似下方 ```python= # -*- coding: utf-8 -*- from Startup import db from sqlalchemy import Column, Integer, String, DateTime, Text class Base_Data(db.Model): __tablename__ = 'base_data' BASE_ID = Column(Integer, primary_key=True, autoincrement=True) Base_Text = Column(Text(), nullable=False) Base_Text2 = Column(String(20), nullable=True) Base_Num = Column(Integer , nullable=True) InertDate = Column(DateTime(), nullable=False) ``` 雖然這樣是可以正常運行的操作資料,但是如果是很多個資料表的情況下,都建立在同一個Model.py裡面的話,對於日後維護和開發更動肯定會帶來不便。 在此筆記框架規劃是建立一個BaseData目錄,內容放置各資料表模型單獨程式檔案,例如有一個資料表叫做Base_Data,建立步驟如下 - [x] 在BaseData目錄內建立一個模型檔```BaseData.py```。 - [x] 在```BaseData.py```內建立一個名為```Base_Data```類別。 - [x] 規劃該類別內變數,每一個變數代表一個欄位,可參考上方程式內容。 * **資料表名稱** 在建置資料表時,如果沒設置```__tablename__```的值就會依照類別名稱來命名,需要注意的是如果有設置```__tablename__```,英文必須為小寫不然migrate在MySQL部份操作會出問題。 ```python= __tablename__ = 'base_data' ``` * **欄位名稱** 用變數宣告建立方式來進行 ``` 欄位名稱 = Column(型態,屬性設定) ``` 建立一個欄位**BASE_ID**,型態為整數,屬性為主鍵、自動遞增 ```python= BASE_ID = Column(Integer, primary_key=True, autoincrement=True) ``` 建立一個欄位**Base_Text**,型態為文字,屬性為不可空值 ```python= Base_Text = Column(Text(), nullable=False) ``` 建立一個欄位**Base_Text2**,型態為長度20字串,屬性為可空值 ```python= Base_Text2 = Column(String(20), nullable=True) ``` 建立一個欄位**Base_Num**,型為整數,屬性為可空值 ```python= Base_Num = Column(Integer , nullable=True) ``` 建立一個欄位**Base_Num**,型態為日期時間,屬性為不可空值 ```python= InertDate = Column(DateTime(), nullable=False) ``` 其餘更進階欄位設定請參考相關參考內容,或在搜尋關鍵字去了解。 Manage.py執行命令控管 -- Flask也有一個動作腳本管理執行方式,透過Flask-Script套件我們可以開發一個動作管理器。 在這裡是建置一個更新資料庫動作,透過Flask-Migrate套件來完成更新修改資料表。 相關參考: [Flask-Script](https://flask-script.readthedocs.io/en/latest/) [Flask-Migrate](https://flask-migrate.readthedocs.io/en/latest/) ### 建立一個更新資料庫動作管理 ```python= # -*- coding: utf-8 -*- from Startup import app,db from flask_script import Manager, Command from flask_migrate import Migrate, MigrateCommand # Create Flask Manager Instance manager = Manager(app) # Create Flask Migrate Instance migrate = Migrate(app, db) # Create manager command for database activity. ex: init(initialize)、migrate、upgrade(commit) manager.add_command('db', MigrateCommand) if __name__ == '__main__': manager.run() ``` 主要程式行,增加一個可識別參數,並設置此參數對應處理的模組。 ``` manager.add_command('db', MigrateCommand) ``` 當執行Manage.py程式時,偵測到一個可識別參數為'db',將此參數值給予Flask-Migrate底下模組MigrateCommand執行對應動作處理。 ``` 1. python manage.py db init 2. python manage.py db migrate 3. python mange.py db upgrade ``` 可用來搭配下方 **資料模型更新腳本** 章節所使用腳本。 uWSGi配置檔 -- uWSGI是一種通信閘道介面應用程式,它是Web服務與後端應用程式之間橋梁,本身也可作為一個Web Server,但是在性能表現上兩者同時兼顧效果還是有限,這時候就有分工情形規劃,在Server配置上使用Nginx負責做Web服務器工作,uWSGI主要負責管理後端應用程序執行,接收Nginx處理好請求內容,分配給對應的後端程序執行完,再回傳結果給Nginx響應即可。 相關參考: [淺談cgi、wsgi、uwsgi 與 uWSGI的區別及應用](https://kknews.cc/code/lzqaobz.html ) [uWSGI详解](https://zhuanlan.zhihu.com/p/36448645) [Configuring uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/Configuration.html#configuring-uwsgi) ### 網站根目錄設置 ```ini= chdir=/web/web_data/ ``` /web/web_data為容器內部位置,在執行容器服務時會將我們指定本機位置掛載在此位置底下,**uwsgi.ini**必須放在指定本機位置內跟著被掛載進來,否則無法進行運作。 ### 在工作負載配置方面 1. 設置一個主程序(master),負責管理底下子程序(worker) ```ini= master=true ``` 2. 設置二個處理子程序(worker) ```ini= processes=2 ``` 3. 每一個處理子程序各分配一個執行緒 ```ini= threads=1 ``` 執行起來後可以在uwsgi/uwsgi.log看到以下訊息 ```log= *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 10) spawned uWSGI worker 1 (pid: 11, cores: 1) spawned uWSGI worker 2 (pid: 12, cores: 1) ``` ### 在端口配置上建立一個管道檔案,讓Nginx能夠透過此檔案跟uWSGI進行對接 ```ini= socket=/tmp/uwsgi.sock ``` 執行起來後可以在容器內部/tmp底下看到**uwsgi.sock**檔案,在/tmp底下還會有**uwsgi.status**與**uwsgi.pid**兩個檔案,前者是負責記錄目前uWSGI運作狀態資訊,後者是紀錄目前uWSGI在系統程序上編號。 **檔案有更動時自動重新加載** ```ini= py-autoreload = 1 ``` 開發環境下可以設置為1代表開啟,如果在正式運作環境下請記得務必設置為0,否則不小心更動檔案會導致uWSGI偵測到檔案更動,重新加載檔案有可能會導致運作上發生錯誤。 **執行成功紀錄:** ```log= *** Starting uWSGI 2.0.18 (64bit) on [Sun Jun 21 13:20:53 2020] *** compiled with version: 8.3.0 on 19 June 2020 13:16:24 os: Linux-4.19.76-linuxkit #1 SMP Tue May 26 11:42:35 UTC 2020 nodename: 688513a0ed4d machine: x86_64 clock source: unix detected number of CPU cores: 2 current working directory: / writing pidfile to /tmp/uwsgi.pid detected binary path: /usr/local/bin/uwsgi !!! no internal routing support, rebuild with pcre support !!! uWSGI running as root, you can use --uid/--gid/--chroot options *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** chdir() to /web/web_data/ your memory page size is 4096 bytes detected max file descriptor number: 1048576 lock engine: pthread robust mutexes thunder lock: disabled (you can enable it with --thunder-lock) uwsgi socket 0 bound to UNIX address /tmp/uwsgi.sock fd 3 uWSGI running as root, you can use --uid/--gid/--chroot options *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** Python version: 3.7.3 (default, Dec 20 2019, 18:57:59) [GCC 8.3.0] Python main interpreter initialized at 0x5570facf8cc0 uWSGI running as root, you can use --uid/--gid/--chroot options *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** python threads support enabled your server socket listen backlog is limited to 100 connections your mercy for graceful operations on workers is 60 seconds mapped 218712 bytes (213 KB) for 2 cores *** Operational MODE: preforking *** WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x5570facf8cc0 pid: 10 (default app) uWSGI running as root, you can use --uid/--gid/--chroot options *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 10) spawned uWSGI worker 1 (pid: 11, cores: 1) spawned uWSGI worker 2 (pid: 12, cores: 1) Python auto-reloader enabled *** Stats server enabled on /tmp/uwsgi.status fd: 11 *** [pid: 12|app: 0|req: 1/1] 172.17.0.1 () {52 vars in 1871 bytes} [Sun Jun 21 13:21:08 2020] GET /index => generated 94 bytes in 21 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0) [pid: 11|app: 0|req: 1/2] 172.17.0.1 () {50 vars in 1782 bytes} [Sun Jun 21 13:21:09 2020] GET /favicon.ico => generated 16 bytes in 2 msecs (HTTP/1.1 404) 2 headers in 86 bytes (1 switches on core 0) [pid: 12|app: 0|req: 2/3] 172.17.0.1 () {50 vars in 1559 bytes} [Sun Jun 21 13:23:01 2020] GET /index => generated 94 bytes in 1 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0) [pid: 12|app: 0|req: 3/4] 172.17.0.1 () {50 vars in 1495 bytes} [Sun Jun 21 13:23:02 2020] GET /favicon.ico => generated 16 bytes in 1 msecs (HTTP/1.1 404) 2 headers in 86 bytes (1 switches on core 0) ``` 靜態檔案目錄、HTML與模板目錄 -- ### 靜態檔案目(static/) 此目錄底下放置著css、js基本檔案之外,開發者可以自行決定要如何規劃放置什麼檔案。 ### HTML與模板目錄(templates/) 此目錄底下放置html檔案,筆者使用Jinja2模板語言進行html開發。 [Jinja2](http://docs.jinkan.org/docs/jinja2/) 資料模型更新腳本 -- 腳本有分為兩種,一種是對應Windows,另一種是對應Linux,但實際工作內容不變,執行上面執行命令控管-更新資料庫動作內容。 1. Windows --> DB_initialize.bat ```bat= @Echo off :: 設置當前bat執行區塊 Setlocal :: 執行更新資料庫Schema結構腳本檔,使用flask-script、flask-migrate :: 透過'Manage.py'程式執行flask-script和flask-migrate :: 使用flask-script管理資料庫更動,命令如下 :: 1. python manage.py db init :: 2. python manage.py db migrate :: 3. python mange.py db upgrade :: 設置所在位置目錄 Set DirPath=E:\Project\IKEA_Project\System_Demo\CASY_Project\ :: 設置migrations目錄名稱 Set DirectoryName=migrations\ :: 判斷 'migrations' 完整路徑是否存在 IF NOT EXIST %DirPath%%DirectoryName% ( echo The [ %DirPath%%DirectoryName% ] is not exists. echo Skip remove action. ) else ( echo The [ %DirPath%%DirectoryName% ] is exists. echo Remove 'migrations' directory. rmdir /s /q %DirPath%%DirectoryName% ) :: 初始化建立migrations目錄 echo Create Initialize 'migrations' Directory , by Run SQLAlchemy init. python Manage.py db init :: 產生資料表結構 echo Run SQLAlchemy migrate. python Manage.py db migrate :: 更新資料表結構 echo Run SQLAlchemy upgrade. python Manage.py db upgrade Endlocal pause ``` 使用前請務必修改 **DirectoryName** 內容,此為網站跟目錄位置。 ```bat= Set DirPath=你的網站跟目錄位置\ ``` 需要注意等號(=)前是不能有空格的,要連在一起否則執行會出錯。 3. Linux --> DB_initialize.sh ```script= # !/bin/bash PATH=/sbin:/bin:/usr/bin # Use source or . command by terminal. # Ex: source script.sh || . script.sh # Not use sh command by terminal. echo echo '執行更新資料庫-資料表資料欄位設定更新.' echo echo '移除migrations目錄' rm -r migrations sleep 1s echo echo '初始化建立migrations目錄' echo python3 Manage.py db init sleep 1s echo echo '產生資料表結構' echo python3 Manage.py db migrate sleep 1s echo echo '更新資料表結構' echo python3 Manage.py db upgrade ```