在 Django 中實現留言刪除功能:完整指南
更新日期: 2024 年 11 月 26 日
本文為 Django 高階教學,第 7 篇:
- 使用 Poetry 管理 Django 專案:完整指南
- 使用 ModelForm 優化 Django 表單與資料庫操作
- Django 留言功能實作指南:從模型設計到應用完成
- Django 留言功能新增與視圖互動詳解
- 在 Django 中實現留言檢索與排序功能:完整指南
- 在 Django 中實現留言換行與顯示時間功能
- 在 Django 中實現留言刪除功能:完整指南 👈 所在位置
- 在 Django 中實現軟刪除功能:完整指南
- 在 Django 中實現軟刪除功能:Fat Model, Thin View
建議閱讀本文前,先閱讀完 Django 進階教學 系列文
本指南將引導您如何在 Django 中實現刪除留言的功能,包括模板設計、URL 配置、視圖函數,以及不同應用間的交互流程。
調整模板以支持刪除留言
我們需要修改 resumes
應用中的 show.html
,為每條留言新增一個刪除按鈕。
調整後的模板
{% extends "shared/layout.html" %}
{% block content %}
{% if messages %}
<div class="alert-box">
{% for message in messages %}
<div class="alert {{ message.tags }}">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
<h1>show! {{ resume.title }}</h1>
<h3>{{ resume.skill }}</h3>
<article>
<p>{{ resume.location }}</p>
<p>{{ resume.content }}</p>
</article>
<footer>
<a href="{% url 'resumes:edit' resume.id %}">編輯</a>
<a href="{% url 'resumes:delete' resume.id %}">刪除</a>
</footer>
<section>
<form action="{% url 'resumes:comments' resume.id %}" method="post">
{% csrf_token %}
<textarea name="content"></textarea>
<button type="submit">新增留言</button>
</form>
</section>
<ul>
{% for comment in comments %}
<li>
{{ comment.content|linebreaksbr }}
<form action="{% url 'comments:delete' comment.id %}" method="post">
{% csrf_token %}
<button type="submit">刪</button>
</form>
<small>{{ comment.created_at }}</small>
</li>
{% endfor %}
</ul>
{% endblock %}
模板中的設計與表單重點
在 Django 中,刪除操作需要依賴 HTML 表單進行提交,以下是設計重點:
為什麼需要表單提交來刪除留言
- HTML 表單的限制
HTML 原生僅支持GET
和POST
方法,並不提供原生的DELETE
方法。因此,我們採用POST
方法來模擬刪除操作。 - 使用
csrf_token
提升安全性
Django 使用 CSRF(跨站請求偽造)保護機制,要求表單中包含唯一的csrf_token
,確保提交的請求來自合法來源。
刪除留言的表單代碼
以下是模板中的刪除留言代碼:
<form action="{% url 'comments:delete' comment.id %}" method="post">
{% csrf_token %}
<button type="submit">刪</button>
</form>
action="{% url 'comments:delete' comment.id %}"
生成指向刪除操作的動態路徑,例如/comments/2
。method="post"
使用POST
方法提交表單,符合 Django 的安全要求。{% csrf_token %}
保護表單提交,避免未經授權的請求。
路徑設計的簡化
- 簡單的路徑設計
刪除操作的路徑設計為/comments/<comment_id>
,例如/comments/2
,避免過於冗長的多級路徑(如/resumes/<resume_id>/comments/<comment_id>
)。 - 路徑簡化的好處
- 符合 RESTful API 的設計原則,專注於對
Comment
資源進行操作。 - 減少冗餘資訊,提高維護性。
- 符合 RESTful API 的設計原則,專注於對
配置 URL 路由
在 comments
應用中新增 urls.py
,配置刪除留言的路由。
comments/urls.py
from django.urls import path
from . import views
app_name = "comments"
urlpatterns = [
path("<int:id>", views.delete, name="delete"),
]
<int:id>
:捕獲需要刪除的留言的 ID。name="delete"
:為此路由定義名稱,便於模板中使用{% url 'comments:delete' comment.id %}
。
實現刪除功能的視圖
在 comments
應用的 views.py
中新增刪除留言的函數。
comments/views.py
from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.http import require_POST
from .models import Comment
@require_POST
def delete(request, id):
# 根據 ID 獲取 Comment,若不存在則返回 404
comment = get_object_or_404(Comment, id=id)
# 刪除留言
comment.delete()
# 返回到 Resume 的詳細頁面
return redirect("resumes:show", id=comment.resume.id)
函數解讀
get_object_or_404
: 確保傳入的 ID 有對應的Comment
,若不存在則返回 404 頁面。- 刪除操作: 調用
comment.delete()
方法,將留言從資料庫中刪除。 - 轉址: 刪除後,使用
redirect
返回到該留言所屬的Resume
詳細頁。
整合主路由
在 mysite
項目的主路由中引入 comments
應用的路由。
mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('pages.urls')),
path('resumes/', include('resumes.urls')),
path('comments/', include('comments.urls')),
]
應用間的交互流程
留言刪除功能涉及兩個應用:resumes
和 comments
,它們需要協同工作以完成刪除操作。
流程概覽
- 模板發起刪除請求
用戶在resumes
應用的模板中點擊刪除按鈕。
表單提交POST
請求至/comments/<comment_id>
,傳遞需要刪除的留言 ID。 comments
應用處理請求
在comments/views.py
中:- 捕獲傳入的留言 ID。
- 刪除對應的
Comment
實例。 - 轉址到
Resume
的詳細頁。
- 轉址至詳細頁
使用redirect
返回Resume
的詳細頁,展示刪除後的留言列表。
交互流程的詳細步驟
模板發送請求
- 所有留言顯示在
resumes
應用的模板中,並且為每條留言提供刪除按鈕。 - 表單提交
POST
請求到/comments/<comment_id>
。
範例模板代碼:
<ul>
{% for comment in comments %}
<li>
{{ comment.content|linebreaksbr }}
<form action="{% url 'comments:delete' comment.id %}" method="post">
{% csrf_token %}
<button type="submit">刪</button>
</form>
<small>{{ comment.created_at }}</small>
</li>
{% endfor %}
</ul>
comments
應用處理請求
comments/views.py
的delete
函數負責處理刪除邏輯:
from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.http import require_POST
from .models import Comment
@require_POST
def delete(request, id):
# 根據 ID 獲取 Comment
comment = get_object_or_404(Comment, id=id)
# 刪除 Comment
comment.delete()
# 轉址回該 Comment 所屬的 Resume 詳細頁
return redirect("resumes:show", id=comment.resume.id)
- 核心代碼解讀
get_object_or_404
:確保提供的 ID 對應一條有效的Comment
,否則返回 404 錯誤。comment.delete()
:調用模型的刪除方法,將資料從資料庫中移除。redirect("resumes:show", id=comment.resume.id)
:通過外鍵反向引用Resume
,返回到該Resume
的詳細頁。
3. 目錄結構與文件說明
以下是項目中與刪除留言功能相關的目錄結構及其作用:
mysite/
├── mysite/
│ ├── urls.py # 主路由,包含 resumes 和 comments 應用的路由
│
├── resumes/
│ ├── templates/
│ │ ├── resumes/
│ │ ├── show.html # 顯示 Resume 的詳細內容和留言列表
│ ├── urls.py # 配置 resumes 應用的路由,包括顯示 Resume 詳情
│
├── comments/
│ ├── urls.py # 定義刪除留言的路由
│ ├── views.py # 實現刪除功能的視圖邏輯
│ ├── models.py # 定義 Comment 模型,與 Resume 建立關聯
小結
透過本指南,我們完成了留言刪除功能的開發:
- 模板設計:
- 在模板中新增刪除按鈕,提交
POST
請求以觸發刪除操作。
- 在模板中新增刪除按鈕,提交
- 路由配置:
- 在
comments/urls.py
中配置刪除留言的路徑。
- 在
- 視圖實現:
- 在
comments/views.py
中完成刪除邏輯,並使用redirect
返回Resume
的詳細頁。
- 在
- 應用交互:
- 確保
resumes
和comments
應用能順暢協作。
- 確保
這種分層設計確保代碼的清晰與高可維護性,是 Django 框架開發的核心思想之一。