Class-Based Views
Views 一頁介紹的是 Function-Based Views(FBV)。Class-Based Views(CBV) 把 View 的邏輯包裝成 Python 類別,Django 內建一整組「通用視圖(generic views)」,把「顯示列表」「顯示單筆」「新增」「修改」「刪除」這些幾乎每個網站都要寫的樣板程式碼先寫好,開發者只需要設定幾個類別屬性(例如 model、template_name)就能運作,比每次都手刻 FBV 省下大量重複程式碼。
官方文件:Class-based views。CBV 內容較多,第一次讀建議先掌握 TemplateView 與 ListView/DetailView,其餘等實際用到再回來查。
RedirectView
如果某個網址只是要把使用者導到另一個網址(例如把網站根目錄導到某個 App 的首頁),不需要真的寫一個 View 函式,用 RedirectView 一行就能完成。
快速做法
from django.urls import path
from django.views.generic.base import RedirectView
urlpatterns = [
path("redirect/", RedirectView.as_view(url="/new-url/"), name="my-redirect"),
]
一般做法
需要重複使用、或想加上其他邏輯時,改成繼承的寫法:
# some_app/views.py
from django.views.generic.base import RedirectView
class MyRedirectView(RedirectView):
url = "/new-url/" # 導向的目標網址
class ExternalRedirectView(RedirectView):
url = "https://www.example.com/" # 也可以導到外部網站
permanent = False # True 為永久重定向(301),預設 False(302)
# urls.py
from django.urls import path
from .views import MyRedirectView, ExternalRedirectView
urlpatterns = [
path("redirect/", MyRedirectView.as_view(), name="my-redirect"),
path("external/", ExternalRedirectView.as_view(), name="external-redirect"),
]
TemplateView
適合單純顯示一個靜態樣板、不需要處理表單或資料庫查詢的頁面,例如「關於我們」。
快速做法
# urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path("about/", TemplateView.as_view(template_name="about.html")),
]
一般做法
# some_app/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "some_app/about.html"
# urls.py
from django.urls import path
from some_app.views import AboutView
urlpatterns = [
path("about/", AboutView.as_view()),
]
FormView
適合「顯示表單 → 驗證 → 處理送出後邏輯」這類流程,但不直接對應某個 Model(例如聯絡我們表單,只是寄一封信,不存進資料庫)。若表單對應到 Model,優先考慮下面的 CreateView/UpdateView。
需要設定的屬性:
form_class:Form 的類別名稱。template_name:Template 名稱。success_url:驗證成功後要導向的網址。form_valid(self, form):驗證成功後要執行的邏輯(例如寄信、寫入紀錄)。
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)
def send_email(self):
# 用 self.cleaned_data 寄信
pass
# views.py
from myapp.forms import ContactForm
from django.views.generic.edit import FormView
class ContactFormView(FormView):
template_name = "contact.html"
form_class = ContactForm
success_url = "/thanks/"
def form_valid(self, form):
# 驗證通過時會呼叫這個方法,必須回傳一個 HttpResponse
form.send_email()
return super().form_valid(form)
ListView、DetailView、CreateView、UpdateView、DeleteView
這五個是最常用的通用視圖,涵蓋資料的完整 CRUD(新增、讀取、修改、刪除),搭配 ModelForm 使用效果最好。官方教學的 Part 4 對這組視圖有完整示範。
ListView
顯示一批資料(例如文章列表)。
官方文件:Generic display views。
常用屬性:
model:要查詢的 Model。queryset:自訂要傳給 Template 的資料,優先於model。context_object_name:預設在 Template 中用object_list存取資料,可用這個屬性改名稱。template_name:預設會找<model名稱小寫>_list.html,可用這個屬性覆寫。
DetailView
顯示單筆資料(例如文章內文),官方教學的 Part 4 有完整範例。
常用屬性:
model:要查詢的 Model。
URLconf 需要傳入主鍵(pk),Django 才知道要顯示哪一筆:
CreateView
顯示新增資料的表單,送出且驗證通過後自動存進資料庫。
常用屬性:
model:要新增的 Model。fields:要開放填寫的欄位(原理與 ModelForm 的fields相同)。success_url:成功後導向的網址。template_name_suffix:預設是"_form",所以預設會找<model名稱小寫>_form.html。
UpdateView
修改既有資料的表單,可以跟 CreateView 共用同一個 Template。
常用屬性與 CreateView 相同(model、fields、success_url、template_name_suffix),主要差異在於 URLconf 需要額外傳入 pk,指定要修改哪一筆資料。
DeleteView
顯示刪除確認頁面,確認後刪除該筆資料。
官方文件:Generic editing views。
# myapp/views.py
from django.urls import reverse_lazy
from django.views.generic.edit import DeleteView
from myapp.models import Author
class AuthorDeleteView(DeleteView):
model = Author
success_url = reverse_lazy("author-list")
<!-- myapp/author_confirm_delete.html -->
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
{{ form }}
<input type="submit" value="Confirm">
</form>
下一步
CRUD 介面做出來之後,通常需要限制只有登入的使用者才能新增或修改資料,請見 後台與使用者驗證。