回文章列表
Web9 分鐘閱讀2026年7月27日

用 30 行 Python 做出你的第一個網站:Flask 入門

#Flask#Python#後端#Web

文章目錄

雙擊 index.html,跟打開 localhost:5000,差在哪?

學完 HTML、CSS、JavaScript 之後,你大概做過一個作品:滑鼠雙擊 index.html,瀏覽器打開,網址列顯示 file:///C:/Users/...。看起來像一個網站,但其實它只是一份「檔案」——你的瀏覽器在讀一份寫死在硬碟上的文字檔,沒有任何程式在背後運算,內容永遠不會變。

真正的網站不是這樣運作的。你在瀏覽器打 google.com,Google 的伺服器收到請求後,跑了一段程式,算出這次要回傳什麼內容,才把結果送回你的瀏覽器。這中間多了一個角色:後端——一台隨時待命、能運算、能查資料庫的伺服器程式。

Flask 就是用 Python 寫這種伺服器最輕量的工具。這篇文章會帶你從安裝開始,寫出第一支會動的網站,看懂「請求進來 → 路由比對 → 函式運算 → 回傳網頁」這個後端最核心的流程。

安裝 Flask

Flask 需要 Python 3.9 以上版本(先在命令列打 python --version 確認)。建議先建一個虛擬環境,避免套件裝進系統全域環境互相打架:

# 建立虛擬環境
python -m venv venv

# 啟動虛擬環境(Windows)
venv\Scripts\activate

# 啟動虛擬環境(macOS / Linux)
source venv/bin/activate

# 安裝 Flask(目前最新穩定版是 3.1.3)
pip install Flask

看到命令列前面出現 (venv) 字樣,代表虛擬環境已啟動。裝完之後可以打 flask --version 確認版本號,看到 Flask 3.1.3 就代表裝好了。

第一支 Flask app:幾行程式看懂請求與回應

在資料夾裡新增一個 app.py,貼上這段:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, Flask!你好,世界'

if __name__ == '__main__':
    app.run(debug=True)

命令列輸入 python app.py,如果看到:

 * Running on http://127.0.0.1:5000

打開瀏覽器連到 http://127.0.0.1:5000(或 http://localhost:5000),就會看到「Hello, Flask!你好,世界」。這一步是本篇最重要的檢查點——沒看到 Running on... 這行字,網頁一定連不上,這是新手最常卡住的第一步,順序記反了(先開瀏覽器、後啟動伺服器)也會出現「無法連線」。

逐行拆解這 8 行在做什麼:

  • Flask(__name__):建立一個 Flask 應用程式實例,__name__ 讓 Flask 知道去哪裡找資源檔案。
  • @app.route('/'):這是一個「裝飾器」,把網址 /(也就是首頁)掛上門牌,交給底下的函式負責。
  • def hello(): return '...':使用者連到這個網址時,Flask 就跑這個函式,把回傳值當作網頁內容送回去。
  • app.run(debug=True):啟動伺服器,debug=True 讓你改程式碼存檔後自動重新載入,錯誤也會直接顯示在瀏覽器上,非常適合開發階段;正式上線前記得改成 False,避免把除錯資訊暴露給訪客。

一個網站,多個路由

一個網站當然不會只有一個頁面。要新增頁面,就是多寫幾組「路由 + 函式」:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return '這是首頁'

@app.route('/about')
def about():
    return '關於我們'

@app.route('/contact')
def contact():
    return '聯絡方式'

if __name__ == '__main__':
    app.run(debug=True)

存檔重跑,現在 /、/about、/contact 三個網址各自對應不同的內容。函式名字(home、about、contact)可以自己取,但兩個路由函式不能同名,Flask 會直接報錯。

路由還可以吃網址裡的變數,這叫動態路由,用 <變數名稱> 包起來即可:

@app.route('/hello/<name>')
def hello_name(name):
    return f'你好,{name}!'

打開 /hello/Jerry,函式裡的 name 就會自動變成字串 "Jerry",畫面顯示「你好,Jerry!」。這一招之後接資料庫查詢(例如 /user/123 查第 123 號會員)會很常用到。

用 render_template 把 HTML 獨立出來

前面的例子都是直接 return 一段文字,實際網站當然要回傳完整的 HTML 頁面,而且 HTML 應該跟 Python 邏輯分開放,不然檔案會愈寫愈亂。Flask 的做法是把 HTML 放進固定名稱的 templates 資料夾(注意有 s,拼錯或放錯資料夾是 TemplateNotFound 錯誤最大的來源),再用 render_template 讀進來:

my_app/
├── app.py
├── templates/
│   └── index.html
└── static/
    └── style.css

templates/index.html 內容:

<!DOCTYPE html>
<html lang="zh-Hant">
<head><meta charset="UTF-8"><title>我的網站</title></head>
<body>
    <h1>哈囉,{{ name }}!</h1>
    <ul>
    {% for hobby in hobbies %}
        <li>{{ hobby }}</li>
    {% endfor %}
    </ul>
</body>
</html>

app.py:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template(
        'index.html',
        name='小明',
        hobbies=['閱讀', '寫程式', '跑步']
    )

if __name__ == '__main__':
    app.run(debug=True)

render_template 的第一個參數是檔名,後面接的關鍵字參數(name='小明')就是傳進模板的資料。HTML 裡的 {{ name }} 和 {% for %} 是 Flask 內建的模板語法 Jinja2,記口訣就好:雙大括號 {{ }} 用來印東西(把變數的值印出來),大括號加百分比 {% %} 用來做邏輯(if 判斷、for 迴圈)。跑起來會看到「哈囉,小明!」加上一份用 <li> 列出的興趣清單——資料是 Python 算出來、傳進去的,不是寫死在 HTML 裡,這就是動態網頁跟純靜態頁面的差別。

卡關自救清單

寫 Flask 時最常見的幾個坑,遇到先對照這張表:

症狀原因
瀏覽器顯示「無法連線」命令列沒看到 Running on http://...,伺服器根本沒啟動成功
TemplateNotFoundHTML 沒放進 templates/ 資料夾,或資料夾名稱、檔名拼錯
Address already in usePort 5000 被前一個沒關掉的 Flask app 佔用,改成 app.run(port=5001) 或先關掉舊的
改了程式碼但畫面沒變debug=True 沒開,或伺服器沒重新啟動
NameError: render_template忘了在最上面 from flask import Flask, render_template

小結

回頭看這篇的路徑:裝好 Flask →寫出最小的一支 app、看到 Running on http://127.0.0.1:5000 → 用路由把一個網站拆成多個頁面、用動態路由接住網址裡的變數 → 用 render_template 把 HTML 獨立成模板、用 Jinja2 把 Python 算出來的資料塞進頁面。這四步就是所有 Flask 網站的骨架,後面不管加資料庫、加表單、串 API,都是在這個骨架上疊功能。

下一步通常是讓網站「能接收使用者輸入」——用 HTML <form> 收資料,後端用 request.form 或 request.args 接住、算完再顯示結果,例如一個填身高體重就能算 BMI 的小工具。如果想把 Flask 學完整、再進階到串接雲端資料庫做圖表、甚至換上 Django 框架做完整 CRUD 後台,可以參考「Python Web 後端」這門課,從 Flask 基礎一路走到網站部署上線。