台南吃貨評分站(上):建立專案,打通前兩條功能
第一次完整走一遍六步建站法。前三步的成果已經在 PROJECT.md 裡;今天從第 ④ 步開始,一次一條功能,做出排行榜與店家頁。
本週結束時你會
今天的時間安排
| 0:00–0:10 | 先看成品長什麼樣子;回顧 PROJECT.md 與上週的排行榜 SQL |
| 0:10–0:45 | 步驟 0【跟著做】建立專案、虛擬環境、初始化資料庫 |
| 0:45–1:15 | 功能 1【跟著做】首頁排行榜:建置、對答案、存檔 |
| 1:15–1:25 | 休息 |
| 1:25–2:10 | 功能 2【自己做】店家頁 |
| 2:10–2:30 | 更新 PROJECT.md 與專案週誌、本週檢核 |
每一條功能都走同一套小流程
- 請 AI 先讀 PROJECT.md,再說明這條功能要改哪些檔案。
- 建置:只做這一條功能,從路由、SQL 到頁面。
- 對答案:用下方的標準答案逐項比對,不對就請 AI 說明原因再修。
- 存檔:Git commit,並更新 PROJECT.md 的功能進度。
口訣:對過答案 → 存檔 → 再做下一條。之後 AI 不管怎麼改壞,都能回到這一版。
專案長這樣
程式設計三/ └─ foodie/ ← 用 Antigravity 開啟這個資料夾 ├─ AGENTS.md 課程規則(課程套件) ├─ .agents/skills/ 存檔、推上 GitHub、上線前檢查(課程套件) ├─ PROJECT.md 專案說明書(複製第 2 週的範例) ├─ app.py Flask 程式:路由與資料庫查詢 ├─ schema.sql 建表 SQL(課程提供) ├─ seed.sql 示範資料:12 間店、49 則評論(課程提供) ├─ templates/ 頁面:base.html、index.html、shop.html … ├─ instance/foodie.db 資料庫檔(由程式產生,不放上 GitHub) ├─ tests/ 自動測試(第 5 週) └─ requirements.txt
步驟 0:建立專案【跟著做】
- 在
程式設計三底下建立foodie資料夾,用 Antigravity 開啟。 - 從課程資源複製
schema.sql、seed.sql、PROJECT_範例_吃貨評分站.md進來,並把最後一個改名成PROJECT.md。 - 把 Antigravity 課程套件的
AGENTS.md與.agents資料夾複製進來。之後說「存檔」「推上 GitHub」就會使用對應的 skill。 - 在 AI 對話框貼上:
請先完整閱讀 PROJECT.md。這是一個 Flask + SQLite 網站,目前資料夾已有 schema.sql 與 seed.sql。 請建立專案骨架,先不要做任何頁面功能: 1. 建立虛擬環境 .venv,安裝 Flask,產生 requirements.txt 2. 建立 app.py:資料庫檔放在 instance/foodie.db;寫一個 get_db() 讓每個請求共用連線,查詢結果可以用欄位名稱取值,並開啟 PRAGMA foreign_keys 3. 加一個指令 flask --app app init-db:執行 schema.sql 與 seed.sql 4. 建立 .gitignore,排除 .venv、instance/、__pycache__ 5. git init 並 commit,訊息「建立專案骨架」 完成後執行 init-db,並用一行 SQL 告訴我 shops 與 reviews 各有幾筆。
常見狀況:Windows 無法啟動虛擬環境
PowerShell 出現「因為這個系統上已停用指令碼執行」:在終端機執行一次 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned,輸入 Y 確認,再重新啟動虛擬環境。這只影響你自己的帳號。
Antigravity 會在建立虛擬環境、安裝套件、執行 git 之前詢問。示範時刻意停下來,念出它要執行的指令,讓學生養成「看清楚再按繼續」的習慣。
功能 1:首頁排行榜【跟著做】
請先讀 PROJECT.md。現在只做這一條功能:「首頁排行榜」。 1. 路由 /:列出所有店家的店名、類別、平均分數(四捨五入到小數 1 位)、評論數 2. 排序:平均分數高到低;同分時評論數多的在前;沒有評論的店排最後,平均分數顯示「尚無評分」 3. 網址參數 ?category=麵 時只顯示該類別;上方提供「全部、飯、麵、小吃、飲料、甜點」的篩選連結,目前的類別要標示出來 4. 頁面用 Jinja 範本:templates/base.html(共用版型,引入 Pico.css)與 templates/index.html 5. SQL 一律用 ? 參數,不可以用字串拼接 只修改 app.py 與 templates/。完成後啟動網站告訴我網址,並說明你的排行榜 SQL 每一行在做什麼。
對答案
| 檢查 | 正確結果 |
|---|---|
| 第 1、2 名 | 派森牛肉湯(4.7,6 則)、函式炒鱔魚(4.7,3 則) |
| 第 4、5 名 | 字典虱目魚粥(4.5,6 則)、迴圈碗粿(4.5,4 則) |
| 最後一名 | 模組肉燥飯,顯示「尚無評分」,評論數 0 |
| 店家總數 | 12 |
| 點「麵」 | 函式炒鱔魚、縮排鍋燒意麵、變數擔仔麵,網址變成 /?category=麵 |
巡堂時最常見的錯誤
只有 11 間店:AI 用了 JOIN 而不是 LEFT JOIN,沒有評論的店消失了。請學生把上週的實作 2 拿出來對照。
派森牛肉湯和函式炒鱔魚順序相反:AI 依四捨五入後的 4.7 排序,再依店名排,忽略了「同分時評論數多者優先」。要求 AI 依照 PROJECT.md 的驗收標準修正。
SQL 用 f-string 組字串:例如 f"WHERE category = '{category}'"。這會造成 SQL 注入漏洞,請學生要求 AI 改成 ? 參數。
排行榜已對過答案,請存檔,訊息「功能1:首頁排行榜」,並把 PROJECT.md 功能進度中的「首頁列出店家」「依類別篩選」「排行榜排序」打勾。
功能 2:店家頁【自己做】
這次沒有提示詞可以複製。照著功能 1 的提示詞結構自己寫,需求如下:
路由 /shop/<id> - 顯示店名、類別、地址 - 平均分數(小數 1 位)與評論數,例如「★ 4.7(6 則評論)」;沒有評論時顯示「尚無評分」 - 所有評論由新到舊:暱稱、星星、短評、時間 - 店家不存在時回應 404,顯示「找不到這個頁面或店家」 - 首頁的店名要能點進來
記得寫上:「請先讀 PROJECT.md」「只做這一條功能」「只修改 app.py 與 templates/」「SQL 用 ? 參數」。
對答案
| 網址 | 正確結果 |
|---|---|
/shop/1 | 派森牛肉湯,★ 4.7(6 則評論),第一則是「小林」4 星「價格合理」 |
/shop/12 | 模組肉燥飯,「尚無評分」,沒有評論 |
/shop/999 | 404,顯示找不到 |
/shop/abc | 404(不是程式錯誤畫面) |
全部正確後存檔:「功能2:店家頁」。
/shop/abc 是刻意加的。若 AI 用 <id> 而非 <int:id>,會在 SQL 查不到後回傳 404,結果碰巧正確;若它直接 int(id) 轉型,則會出現 500 錯誤。兩種寫法都讓學生看看,討論「讓框架先擋下錯誤輸入」的好處。
收尾:更新文件
- 確認 PROJECT.md 的功能進度已打勾。
- 在專案工具包的「每週進度紀錄」寫下:完成了什麼、AI 犯了什麼錯、下週要做什麼。
本週檢核
第 5 週預告:讓使用者寫評論、新增店家,並用自動測試證明每一條驗收標準都做到了。