by:陳澤榮 (timothychenpc@gmail.com)
這個網站本身時用於四校聯合暑訓(楓落景畔遇建成),然後仍然沒有採用
RESTful
的方式設計api
,所以忍耐一下😂基本資訊
- 網址
- Github位置
- Hackmd
目標
功能
- 介紹暑訓的內容(暑訓的時間,內容,友社以及報名資訊等)
- 報名功能(要可以進行檔案上傳)
開發
頁面以及路由設計
主頁 / [get]
這個頁面的設計和製作都是由
WhiteCat
進行的,但是因為是使用react
框架(採用js
渲染html
的元素)進行的前端的撰寫,因為不是傳統的html
和css
的格式,所以在和後端flask
合併的過程中有很多的問題出現(也常常會出現跟flask
的模板引擎Jinja2
打架的情況)報名表單 /join [get, post]
這個頁面因為需要進行表單驗證(同時包含
csrf_token
)所以這邊我們使用html
和css
重新寫了一次,然後這次網站的報名因為想要跟一般傳統的google
表單所搭建的報名做出區別,所以我們就一樣需要去找其他的儲存空間(但是因為我個人比較熟NoSQL
所以最終採用Mongodb
作為所有內容的儲存)然後這個路由支援兩個方法一個是一般的
get
一個是post
請求,而post
請求主要就是因為表單是通過post
請求封裝在request body
進行傳輸的,然後表單驗證的部分分為以下兩個部分:- 一般的表單內容
一般表單內容的部分我是採用
wtforms
進行後端驗證(前端只有進行required
驗證),然後
wtforms
的好處就是你可以使用物件的方式構建你的表單,然後再使用jinja2
插入到html
中渲染整個表單的內容(而且還自帶csrf_token
的功能)- 小黃卡的檔案
這邊進行檔案內容的上傳因為檔案的大小絕對不會超過
16MB
所以我就沒有使用GridFS
而是直接使用一般的document
進行儲存,然後在整個檔案上傳和處理的部分會經過幾個步驟:- 上傳檔案
- 檢查檔案大小(限制每個檔案
3MB
) 如果檔案大小超過3MB
則會觸發http 413
的錯誤(比較高層級的錯誤),然後可以自定義error handler
去管理頁面
- 檢查檔案格式(
pdf, png, jpg, jpeg, HEIC
) 不符合則在產生回應的時候客製化進行回應(檔案格式不符合)
- 檔案名稱(避免因為空格或者斜線影響到檔案系統的儲存,類似注入)
這邊是使用
werkzeug.utils
套件的secure_filename
將檔案名稱安全化
- 寫入暫存 因為好像沒有辦法直接將內容進行上傳(沒有找到獲取那個file物件的原數據的方法)
- 將檔案上傳到
mongodb
這邊就是比較一般的上傳只是上傳的內容都是二進制的檔案內容
- 清除暫存
*HEIC是iphone的圖片檔案格式
數據庫設計
mongodb └───izcc捷大(DB) │ └───games(Collection) │ └───settings(Collection) └───izcc_join報名網站(DB) │ └───data 一般資料(Collection) │ └───file 小黃卡資料(Collection)
這次一樣是採用
NoSQL
作為這次的主要的儲存,然後以上是這次網站的數據庫架構,然後可以發現最主要報名的內容都是放在data
和file
這兩個collection
中,針對於檔案儲存的部分,這次沒有考慮使用blob
之類的東西,想要直接一次都存放在mongodb
中,而mongodb
支援兩種檔案存儲的方式:- 一個
document
放一個檔案的數據(16mb
以內)
- 使用
gridFS
針對檔案進行切分,放在不同的document
(16mb
以上)
因為這次所有需要儲存的檔案只有圖片(小黃卡),所以可以直接使用第一種方案,使用單一
document
管理我們的數據。檔案設計
izcc2022summer | README.md 說明文件 | download_file.py 輸出名單+下載小黃卡 | requirements.txt 依賴資源 | app.py 主程式(包含伺服器設定) | └───main 主要後端檔案的所在 | | __init__.py | | model.py 進行物件設計 | | forms.py 表單驗證 | | routes.py 路由管理 └───static 靜態資料 │ └───js │ └───css │ └───media 影像資源 └───templates html檔案 │ | index.html │ | join.html
debug設計
這次比較沒有設計完整系統性的
debug
的終端機輸出,但是有針對報名的結果使用line notify
對目前狀況進行掌握(在報名成功的時候傳送姓名,出錯的時候傳送錯誤訊息等)。但是之後還是要研究如何針對每一個請求的處理過程進行解析,才能更有效率地進行debug
以及更快速的掌握問題的發生。另外一點就是雲端部署時的終端機資訊掌握(因為沒有這些內容基本上在雲端環境發生的問題就會根本沒有辦法進行分析跟解決)。
成果
主頁
報名
心得
K(keep)
- 數據庫結構的設計 (有將一般的資料跟檔案分開,避免存取一般資料的時候因為需要載入的內容過大而卡頓)
- 有學會檔案存儲
- 有串接
line notify
在報名成功和報錯的時候進行反饋 (可以不用使用電腦就可以了解目前的情況,提高了debug
等的效率)
- 開發過程迅速
- 有為了在
mongodb
存儲檔案開發輸出工具 (download_file.py
用於將用戶資料輸出excel
,並將所有在mongodb
中以二進制存儲的檔案數據轉成對應的檔案格式輸出)
C(challenge)
react
和flask
的合併
- 修改
react
產生的js
(整個過程跟打ctf
一樣刺激) 就連改一下文字,因為這個檔案沒有中文(只有unicode
),所以還要encode
成unicode
然後搜索,然後修改
- 檔案存儲
(因為之前真的完全沒有嘗試過再
mongodb
儲存完整的檔案)
- 多人協作
S(stop)
- 沒有了解原理、只為了目的
- 沒有做好
debug
資料的管理 (可能需要更全面和不同時間段的debug
資料)
- 不會
react
和flask
合併
- 沒有好好管理相關的路由和方法
- 有些操作沒有考慮好使用者回饋 (讓使用者對目前的狀態感到困惑)
- 沒有設計好多人協作的
workflow
(導致有時候沒有辦法通過git pull push
完成合併等問題,最後還是會通過dc
進行檔案的傳輸或者是從zip
找檔案來使用)
- 每次都在重複寫一些功能
(下載,輸出
excel
之類的)
S(start)
- 搞清楚
decorators
的原理
- 可能要想辦法有效率地輸出每一個請求的處理過程
(包含經過哪些函式,每一個函式分別的
input
和output
是什麼)
- 要去搞清楚
react
怎麼跟flask
合併
- 可能要採用
RESTful
的方式針對api
進行管理 (通過http
的method
區分不同的用途,然後用物件式進行處理)
- 多使用彈窗隊使用者進行回饋
- 可能需要規範
workflow
(包含什麼時候需要commit
,什麼時候需要進行merge
之類的,然後避免git
以外的操作)
- 考慮構建自己的
tool kit
(然後將功能進行封裝,然後需要的時候可以直接調用,避免重複寫)