今回の投稿はDjangoクラスベースビュー(CBV)シリーズの第5回で、CreateView、UpdateView、DeleteViewを使ってCRUDを簡単に実装する方法について説明します。前回の記事で取り上げたListViewDetailViewと組み合わせることで、データの取得だけでなく、作成(Create)修正(Update)削除(Delete)が可能な完全なCRUDアプリケーションを迅速に構成できます。

前回の記事のListView、DetailViewをまだ読んでいない方は、まず以前の記事を読まれることをお勧めします。

クラスベースビュー(CBV)探求シリーズ④ - ListView & DetailViewの活用法


「Djangoのジェネリックビューで簡単にCRUDを完成させ、生産性を最大化しましょう!」

これまでの投稿ではCBVの基本構造とListViewDetailViewを通じて読み取り(READ)作業に焦点を当ててきました。
今回の記事では、Djangoが提供する便利なCreateViewUpdateViewDeleteViewを見て、作成(Create)修正(Update)削除(Delete)機能を統一的に持つWebアプリケーションを完成させてみましょう。


1. CreateView – データを作成する

1.1 基本概念と構造

CreateViewはDjangoのジェネリックビューの中で「新しいオブジェクトを作成する」ことに特化したクラスです。

  • フォーム処理を自動化: FormView機能を内部的に利用し、form_valid()内で新しいオブジェクトを保存し成功時にはURLにリダイレクトします。

  • ModelFormと相性抜群: model属性とfields、またはform_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>

Tip: fieldsの代わりにform_classを使用すると、forms.pyModelFormを定義してより細かくフォームを制御できます。


2. UpdateView – データを修正する

2.1 基本概念と構造

UpdateView既存のオブジェクトを探して修正することに特化したジェネリックビューです。

  • URLにpkまたはslugの値を使用して、該当オブジェクトを自動的に検索します。

  • フォームには既存のデータが自動的に入力された状態でレンダリングされ、ユーザーが修正して送信するとDBに変更が保存されます。

# 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がすでにDBに保存されているオブジェクトであるため、既存のデータがフォームに自動入力されます。


3. DeleteView – データを削除する

3.1 基本概念と構造

DeleteViewは特定のオブジェクトを探して削除するために使用されるジェネリックビューです。

  • ユーザーが削除確認フォームを送信すると、該当オブジェクトがDBから削除され、指定された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 Actions, 5 Views

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) READ
    path('posts/', PostListView.as_view(), name='post_list'),                   # 一覧(ListView)
    path('posts/<int:pk>/', PostDetailView.as_view(), name='post_detail'),      # 詳細(DetailView)

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

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

    # 4) DELETE
    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などと組み合わせて「ログインユーザーのみが作成/更新/削除できる」ようにできます。

  • 権限を詳細に管理したい場合はPermissionRequiredMixinまたはUserPassesTestMixinも検討してみてください。


6. FBVと比較してみる

機能 FBV(関数ベースビュー) Create/Update/DeleteView(クラスベースビュー)
作成(Create) request.method == 'POST'条件文、ModelFormを直接定義、保存ロジックを直接作成 CreateView: 相続するだけでフォーム作成→保存→リダイレクトが自動処理されます
修正(Update) 既存のオブジェクトを取得しフォームに入れ、POST処理時に再度検証・保存ロジックを繰り返します UpdateView: 既存のオブジェクトを取得→修正→保存、ロジックが自動化
削除(Delete) GET→削除確認ページをレンダリング、POST→削除処理、リダイレクトなどのロジックがすべて関数内に混在します DeleteView: 削除対象オブジェクトを取得→削除後の移動処理など全て組み込みロジックを提供
可読性 / メンテナンス ロジックの分岐が多くなり、コードが長くなりがちで、複数の場所で同じロジックが重複 メソッドオーバーライドで必要な部分のみを再定義し、重複を最小化可能
開発生産性(核心キーワード) 「手作業が多く、時間を消費し、コードの重複」 「開発速度向上(時間節約)とメンテナンス性改善(生産性の向上)」

FBV vs CBV – 組み立て式家具の比喩


7. まとめ: ジェネリックビューを使ってCRUDを迅速かつきれいに実装しよう!

CreateViewUpdateViewDeleteViewを活用すれば、DjangoでCRUD操作を極めて簡潔で直感的なコードで完成できます。
特に重複するフォーム処理ロジックや、データ保存後のリダイレクトなどのパターンが自動的に処理されるため、開発者が集中すべき部分は「ビジネスロジック」と「UI/UX」になります。

これでListView + DetailView + CreateView + UpdateView + DeleteViewをすべて理解できたなら、Djangoで基本的なCRUDアプリケーションを簡単に構成することができます!

次回の記事ではTemplateView & RedirectViewを取り上げ、シンプルなページレンドリングリダイレクト処理をスムーズに自動化する方法を見ていく予定です。


前回の記事を振り返る

  1. クラスベースビュー(CBV)探求シリーズ #1 – FBVからCBVへの移行理由と開発者の姿勢

  2. クラスベースビュー(CBV)探求シリーズ #2 – Djangoの基本Viewクラスを理解する

  3. クラスベースビュー(CBV)探求シリーズ #3 – FormViewでフォーム処理を簡単にする

  4. クラスベースビュー(CBV)探求シリーズ #4 – ListView & DetailViewの活用法


「Djangoのジェネリックビューを活用してCRUD実装を自動化し、
プロジェクトの開発スピードとコード品質を同時に向上させましょう!」