Django CRUD(不使用 ModelForm)入門教學筆記 | 學習筆記

Posted by kdchang on 2024-08-31


前言

在 Django 中,ModelForm 提供了一個快速建立表單與驗證的工具,但在某些情境下,我們可能希望自己掌控表單結構與驗證流程。這篇筆記將示範如何不依賴 ModelForm,手動實作一套 CRUD 系統,幫助你更深入理解 Django 表單處理的基本原理。

我們將製作一個簡單的「書籍管理系統」,支援新增(Create)、讀取(Read)、更新(Update)與刪除(Delete)書籍資訊。

1. 建立 Django 專案與應用

首先,安裝 Django 並建立新的專案與應用:

pip install django
django-admin startproject myproject
cd myproject
python manage.py startapp books

註冊 books 應用於 myproject/settings.pyINSTALLED_APPS

INSTALLED_APPS = [
...
'books',
]

2. 定義模型(Model)

books/models.py 中定義一個簡單的書籍模型:

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()

def __str__(self):
return self.title

遷移資料庫:

python manage.py makemigrations
python manage.py migrate

3. 撰寫 Views(不使用 ModelForm)

books/views.py 中撰寫手動處理的 CRUD 功能。

新增書籍(Create)

from django.shortcuts import render, redirect
from .models import Book
from django.utils.dateparse import parse_date

def create_book(request):
if request.method == 'POST':
title = request.POST.get('title')
author = request.POST.get('author')
published_date_str = request.POST.get('published_date')
published_date = parse_date(published_date_str)

if title and author and published_date:
Book.objects.create(title=title, author=author, published_date=published_date)
return redirect('book_list')
else:
error = "所有欄位皆為必填"
return render(request, 'books/book_form.html', {'error': error})
return render(request, 'books/book_form.html')

讀取書籍(Read)

def book_list(request):
books = Book.objects.all()
return render(request, 'books/book_list.html', {'books': books})

更新書籍(Update)

from django.shortcuts import get_object_or_404

def update_book(request, pk):
book = get_object_or_404(Book, pk=pk)
if request.method == 'POST':
title = request.POST.get('title')
author = request.POST.get('author')
published_date_str = request.POST.get('published_date')
published_date = parse_date(published_date_str)

if title and author and published_date:
book.title = title
book.author = author
book.published_date = published_date
book.save()
return redirect('book_list')
else:
error = "所有欄位皆為必填"
return render(request, 'books/book_form.html', {'book': book, 'error': error})
return render(request, 'books/book_form.html', {'book': book})

刪除書籍(Delete)

def delete_book(request, pk):
book = get_object_or_404(Book, pk=pk)
if request.method == 'POST':
book.delete()
return redirect('book_list')
return render(request, 'books/book_confirm_delete.html', {'book': book})

4. 設定 URL 路由

books/urls.py 中設定對應的路由:

from django.urls import path
from . import views

urlpatterns = [
path('', views.book_list, name='book_list'),
path('create/', views.create_book, name='create_book'),
path('update/<int:pk>/', views.update_book, name='update_book'),
path('delete/<int:pk>/', views.delete_book, name='delete_book'),
]

並在 myproject/urls.py 引入 books 路由:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('books/', include('books.urls')),
]

5. 建立模板(Templates)

手動撰寫簡單的 HTML 表單與顯示畫面。

book_list.html

<h1>書籍列表</h1>
<a href="{% url 'create_book' %}">新增書籍</a>
<ul>
{% for book in books %}
<li>
{{ book.title }} - {{ book.author }} - {{ book.published_date }}
<a href="{% url 'update_book' book.id %}">編輯</a>
<a href="{% url 'delete_book' book.id %}">刪除</a>
</li>
{% endfor %}
</ul>

book_form.html

<h1>{% if book %}編輯書籍{% else %}新增書籍{% endif %}</h1>

{% if error %}
<p style="color:red;">{{ error }}</p>
{% endif %}

<form method="post">
{% csrf_token %}
<p>
標題:<input type="text" name="title" value="{{ book.title|default_if_none:'' }}">
</p>
<p>
作者:<input type="text" name="author" value="{{ book.author|default_if_none:'' }}">
</p>
<p>
出版日期(格式 yyyy-mm-dd):<input type="text" name="published_date" value="{{ book.published_date|default_if_none:'' }}">
</p>
<button type="submit">儲存</button>
</form>

<a href="{% url 'book_list' %}">返回列表</a>

book_confirm_delete.html

<h1>刪除書籍</h1>
<p>確定要刪除 "{{ book.title }}" 嗎?</p>
<form method="post">
{% csrf_token %}
<button type="submit">確定刪除</button>
</form>
<a href="{% url 'book_list' %}">取消</a>

6. 啟動伺服器測試

啟動 Django 開發伺服器:

python manage.py runserver

在瀏覽器開啟 http://127.0.0.1:8000/books/,你將可以新增、查詢、編輯和刪除書籍。


總結

這篇教學示範了在 不使用 ModelForm 的情況下,手動撰寫表單處理與資料驗證,完整實作了 Django 的 CRUD 功能。

這種方式的優點在於靈活度高,你可以完全控制表單的結構、驗證邏輯與錯誤處理,非常適合需要客製化表單行為或前後端分離的專案。不過,相較於使用 ModelForm,開發成本略高,也容易產生重複程式碼,因此適時選擇工具是重要的工程判斷。

進一步的優化方向包括:

  • 加入更完整的資料驗證
  • 增加欄位格式錯誤提示
  • 使用 JavaScript 增強表單互動
  • 將表單資料與邏輯封裝成 Class-Based Views(CBV)

透過本篇範例,希望你對 Django 低階處理表單與 CRUD 流程有更深入的理解。


歡迎分享按讚給予支持和鼓勵!


Related Posts

Comments