今天完成整個網站最重要的一組功能。
步驟 1:建立編輯路由
在 app.py 中加入:
@app.route("/media/int:media_id/edit", methods=["GET", "POST"])def edit_media(media_id): connection = get_db_connection() item = connection.execute(""" SELECT * FROM media WHERE id = ? """, (media_id,)).fetchone() if item is None: connection.close() return "找不到這筆作品", 404 if request.method == "POST": title = request.form.get("title", "").strip() media_type = request.form.get("media_type", "") year_text = request.form.get("year", "").strip() genre = request.form.get("genre", "").strip() status = request.form.get("status", "") rating_text = request.form.get("rating", "").strip() notes = request.form.get("notes", "").strip() if not title: connection.close() flash("作品名稱不能空白。", "error") return redirect(url_for("edit_media", media_id=media_id)) if media_type not in ("movie", "game"): connection.close() flash("作品類型不正確。", "error") return redirect(url_for("edit_media", media_id=media_id)) allowed_statuses = { "movie": {"backlog", "watched"},
步驟 2:建立 templates/edit.html
{% extends "base.html" %}
{% block title %}編輯收藏 - My Media Library{% endblock %}
{% block content %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
{{ message }}
{% endfor %}
{% endwith %}
<label for="media_type">作品類型 *</label>
<select id="media_type" name="media_type" required>
<option value="movie"
{% if item['media_type'] == 'movie' %}selected{% endif %}>
電影
</option>
<option value="game"
{% if item['media_type'] == 'game' %}selected{% endif %}>
遊戲
</option>
</select>
<label for="year">年份</label>
<input id="year" name="year" type="number"
min="1888" max="2100"
value="{{ item['year'] or '' }}">
<label for="genre">分類</label>
<input id="genre" name="genre" type="text"
maxlength="50"
value="{{ item['genre'] or '' }}">
<label for="status">狀態</label>
<select id="status" name="status">
{% for value, label in [
('backlog', '待觀看/待遊玩'),
('watched', '已看電影'),
('playing', '遊玩中'),
('completed', '已通關')
] %}
<option value="{{ value }}"
{% if item['status'] == value %}selected{% endif %}>
{{ label }}
</option>
{% endfor %}
</select>
<label for="rating">個人評分(1–10)</label>
<input id="rating" name="rating" type="number"
min="1" max="10"
value="{{ item['rating'] or '' }}">
<label for="notes">個人心得</label>
<textarea id="notes" name="notes"
rows="5" maxlength="2000">{{ item['notes'] or '' }}</textarea>
<button class="button" type="submit">儲存修改</button>
這裡的 value="{{ item['title'] }}" 會預先填入舊資料,讓使用者不用每次重新輸入所有欄位。
步驟 3:建立刪除路由
在 app.py 加入:
@app.route("/media/int:media_id/delete", methods=["POST"])def delete_media(media_id): connection = get_db_connection() try: cursor = connection.execute(""" DELETE FROM media WHERE id = ? """, (media_id,)) connection.commit() deleted = cursor.rowcount > 0 finally: connection.close() if deleted: flash("收藏已刪除。", "success") else: flash("找不到這筆作品。", "error") return redirect(url_for("home"))
刪除使用 POST,而不是讓使用者點開一個網址就直接刪除資料。這樣比較符合操作的預期,也能降低誤刪風險。
步驟 4:測試完整 CRUD
依序操作: