本文是 Django 基于类的视图(CBV)系列的第五篇,主要介绍如何通过 CreateView、UpdateView、DeleteView 容易地实现 CRUD。结合之前提到的 ListViewDetailView,可以快速构建一个完整的 CRUD 应用程序,支持 数据读取创建(Create)修改(Update)删除(Delete) 功能。

如果您还没有阅读上一篇文章 ListViewDetailView,建议您先阅读之前的内容。

基于类的视图(CBV)探索系列 ④ - ListView 和 DetailView 的使用方法


“利用 Django 的通用视图轻松完成 CRUD,提高生产力!”

在之前的文章中,我们关注了 CBV 的基本结构以及通过 ListViewDetailView 进行的 读取(READ) 操作。
在本文中,我们将探讨 Django 提供的便捷的 CreateViewUpdateViewDeleteView,使得创建(Create)、修改(Update) 和 删除(Delete) 的功能可以系统化地完善应用程序。


1. CreateView – 创建数据

1.1 基本概念和结构

CreateView 是 Django 通用视图中专门用于“创建新对象”的类。

  • 自动化表单处理: 内部利用 FormView 功能,在 form_valid() 中保存新对象并在成功时重定向到指定 URL。

  • 与 ModelForm 配合良好: 指定 model 属性及 fieldsform_class,即可自动生成并处理表单。

# views.py
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Post

class PostCreateView(CreateView):
    model = Post
    fields = ['title', 'content']  # 或者 form_class = PostForm
    template_name = 'post_form.html'
    success_url = reverse_lazy('post_list')  # 创建成功后转到的 URL

1.2 urls.py 连接示例

# urls.py
from django.urls import path
from .views import PostCreateView

urlpatterns = [
    path('posts/create/', PostCreateView.as_view(), name='post_create'),
]

1.3 模板示例: post_form.html

<!DOCTYPE html>
<html>
<head>
    <title>撰写新文章</title>
</head>
<body>
    <h1>撰写新帖子</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">保存</button>
    </form>
</body>
</html>

提示: 使用 form_class 替代 fields 可以在 forms.py 中定义 ModelForm,以更精细地控制表单。


2. UpdateView – 修改数据

2.1 基本概念和结构

UpdateView 是专门用于查找并 修改 现有对象 的通用视图。

  • 使用 URL 中的 pkslug 值自动查询相关对象。

  • 表单渲染时会自动填入现有数据,用户修改后提交后,变更将保存到数据库。

# views.py
from django.views.generic.edit import UpdateView
from django.urls import reverse_lazy
from .models import Post

class PostUpdateView(UpdateView):
    model = Post
    fields = ['title', 'content']
    template_name = 'post_form.html'
    success_url = reverse_lazy('post_list')  # 修改成功后转到的 URL

2.2 urls.py 连接示例

# urls.py
from .views import PostUpdateView

urlpatterns = [
    path('posts/<int:pk>/edit/', PostUpdateView.as_view(), name='post_update'),
]

2.3 模板示例(可重用)

与 CreateView 类似,可以重用 post_form.html 模板。
UpdateView 中,form.instance 已经是数据库中保存的对象,因此现有数据会自动填入表单。


3. DeleteView – 删除数据

3.1 基本概念和结构

DeleteView 是查找特定对象并进行 删除 的通用视图。

  • 用户提交删除确认表单后,相关对象将从数据库中移除,并重定向到指定 URL。

  • 为了安全起见,建议创建一个“删除确认”的模板。

# views.py
from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from .models import Post

class PostDeleteView(DeleteView):
    model = Post
    template_name = 'post_confirm_delete.html'
    success_url = reverse_lazy('post_list')

3.2 urls.py 连接示例

# urls.py
from .views import PostDeleteView

urlpatterns = [
    path('posts/<int:pk>/delete/', PostDeleteView.as_view(), name='post_delete'),
]

3.3 模板示例: post_confirm_delete.html

<!DOCTYPE html>
<html>
<head>
    <title>删除帖子</title>
</head>
<body>
    <h1>删除帖子</h1>
    <p>您确定要删除这篇文章吗?</p>
    <form method="post">
        {% csrf_token %}
        <button type="submit">删除</button>
        <a href="{% url 'post_list' %}">取消</a>
    </form>
</body>
</html>

注意: DeleteView 被设计成要经过“删除确认”流程,以防止用户误删。
如果想要直接删除,必须使用其他方式(如 FormView 或直接编写逻辑)实现。


4. 一览 CRUD 完成流程

CRUD 概念图 – 4 个操作与 5 个视图

4.1 示例模型: Post

# models.py
class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.title

4.2 urlpatterns(简化版本)

urlpatterns = [
    # 1) 读取
    path('posts/', PostListView.as_view(), name='post_list'),                   # 列表(ListView)
    path('posts/<int:pk>/', PostDetailView.as_view(), name='post_detail'),      # 详细(DetailView)

    # 2) 创建
    path('posts/create/', PostCreateView.as_view(), name='post_create'),

    # 3) 更新
    path('posts/<int:pk>/edit/', PostUpdateView.as_view(), name='post_update'),

    # 4) 删除
    path('posts/<int:pk>/delete/', PostDeleteView.as_view(), name='post_delete'),
]

4.3 推荐的目录结构和模板文件

  • templates/

    • post_list.html

    • post_detail.html

    • post_form.html(CreateView 和 UpdateView 共用)

    • post_confirm_delete.html(DeleteView)


5. 如何自定义 Create/Update/DeleteView

5.1 使用 form_class 进行细分表单控制

class PostCreateView(CreateView):
    model = Post
    form_class = PostForm  # 指定 ModelForm
    ...

PostForm 可以更详细地设置 字段验证小部件指定,以实现更灵活的表单处理。

5.2 使用 get_success_url() 进行动态重定向

def get_success_url(self):
    # 例如: 使用新创建的 Post 的 pk 转到详细页面
    return reverse_lazy('post_detail', kwargs={'pk': self.object.pk})

self.object 指向当前 Create/Update 正在处理的模型实例。

5.3 添加权限控制,使用 Mixin

  • 可以与 LoginRequiredMixin 等结合,实现“仅登录用户可以创建/修改/删除”的功能。

  • 如果希望更细致地管理权限,可以考虑使用 PermissionRequiredMixinUserPassesTestMixin


6. 与 FBV 进行比较

功能 FBV (函数基视图) Create/Update/DeleteView (基于类的视图)
创建(Create) request.method == 'POST' 条件语句,手动定义 ModelForm,手动编写保存逻辑 CreateView: 继承后表单的创建、保存和重定向都自动处理
修改(Update) 获取现有对象后放入表单,再次检验及保存逻辑重复 UpdateView: 自动加载现有对象 -> 修改 -> 保存
删除(Delete) GET -> 渲染删除确认页面,POST -> 进行删除处理,重定向逻辑混杂在函数中 DeleteView: 获取删除目标对象、删除并处理重定向都提供内置逻辑
可读性 / 维护性 由于逻辑分支太多,代码容易变长,多个地方重复相同逻辑 通过 方法重写 仅重写所需部分,最小化重复
开发生产力(核心关键词) “手动操作多,时间消耗大,代码重复” “提高开发速度(节省时间)和维护性提升(生产力增强)”

FBV vs CBV – 组装家具比喻


7. 总结:通过通用视图快速实现 CRUD!

利用 CreateViewUpdateViewDeleteView,您可以以极其简洁和直观的代码在 Django 中完成 CRUD 操作。
特别是,自动处理的 重复表单处理逻辑数据保存后的重定向,使得开发者可以专注于“业务逻辑”和“UI/UX”。

现在,如果您已经理解 ListView + DetailView + CreateView + UpdateView + DeleteView,就可以轻松构建基本的 CRUD 应用程序了!

在下一篇文章中,我们将讨论 TemplateView 和 RedirectView,探索如何顺利自动化 简单页面渲染重定向 处理。


回顾上一篇文章

  1. 基于类的视图(CBV)探索系列 #1 – 从 FBV 转向 CBV 的原因及开发者的态度

  2. 基于类的视图(CBV)探索系列 #2 – 理解 Django 的基本视图类

  3. 基于类的视图(CBV)探索系列 #3 – 使用 FormView 轻松处理表单

  4. 基于类的视图(CBV)探索系列 #4 – ListView 和 DetailView 的使用方法


“通过利用 Django 的通用视图,自动化 CRUD 实现,
同时提升项目开发速度和代码质量!”