【Django】UpdateViewの使い方(クラスベースビューでのレコード更新ページの実現)

UpdateViewでのクラスベースビューの実現方法解説ページアイキャッチ

このページにはプロモーションが含まれています

このページでは、Django フレームワークで定義される UpdateView の使い方について説明していきます。

この UpdateViewView というクラスのサブクラスの1つであり、ビューをクラスベースで作成する際に利用するクラスとなります。この View のサブクラス を継承し、さらにクラス変数を定義したりメソッドをオーバーライドすることで、あなたが開発したいアプリに応じたビューを作成することが可能となります。

この辺りのクラスベースビューやクラスベースビューの作り方については下記ページで解説していますので、詳しくはこちらをご参照ください。

クラスベースビューの解説ページアイキャッチ 【Django入門14】クラスベースビューの基本

また、この UpdateView は、View のサブクラス である CreateViewDetailView と密接に関連しています。というか、この2つのクラスについて理解しておけば UpdateView を簡単に使いこなすことができます。これらのクラスについては下記ページで解説していますので、これらのクラスについて理解されていない方は、事前に下記ページを読んでいただくことをオススメします。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現) DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現)

UpdateView

では、UpdateView について解説していきたいと思います。

UpdateView は、名前の通り、データベースに既に保存されているレコードの更新を行うページを実現する View のサブクラス となります。

UpdateViewdjango.views.generic から import して利用します。

UpdateViewのimport
from django.views.generic import UpdateView

例えば、登録済みのユーザーの情報の更新ページ、投稿済みのコメントの修正ページといった、データベースに保存されているレコードの更新を行うためのページを実現するのが UpdateView となります。

UpdateViewで実現できるページの例

UpdateView = CreateView + DetailView

ページの冒頭でも触れましたが UpdateView は下記ページで紹介している CreateView と DetailView と関係性が深いです。イメージとしては UpdateView = CreateViewDetailView となります。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現) DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現)

CreateView の解説ページでも説明していますが、CreateView では GET リクエストを受け取った際には基本的には空のフォームを表示し、さらにフォームからデータが送信されて POST リクエストを受け取った際には、その送信されてきたデータをインスタンス(レコード)としてデータベースに新規登録されるようになっています。念の為補足しておくと、クラス変数 initialの定義によって、表示されるフォームに初期値を入力しておくことも可能です。

CreateViewの動作

これに対し、UpdateView では GET リクエストを受け取った際に、まずデータベースから更新対象となるインスタンス(レコード)の取得が行われます。そして、そのインスタンスの各種フィールドの情報をフィールドにセットした状態のフォームを表示します。これによって、ユーザーが更新前の各種フィールドの情報を確認し、更新すべきフィールドがどれであるかを判断することができるようになります。

UpdateViewでのフォーム表示時の動作

さらに、ユーザーが更新したいフィールドの情報を修正し、ボタンのクリック等でフォームからデータが送信されると POST リクエストがウェブアプリに送信されます。そして、そのリクエストを UpdateView が受け取ります。この POST リクエストを受け取った際にも最初に行われるのはデータベースからの更新対象となるインスタンス(レコード)の取得となります。

UpdateViewでのインスタンス保存時の動作1

そして、そのインスタンスを送信されてきたデータで上書きし、それをデータベースに保存することでインスタンスの更新が実現されることになります。

UpdateViewでのインスタンス保存時の動作2

ここで CreateViewUpdateView との違いについて考えると、これは基本的に、リクエストを受け取った際のデータベースからのインスタンスの取得の有無のみとなります。

MEMO

データベースから取得したインスタンスの各種フィールドの情報をフォームにセットした状態で表示する点や、データベースから取得したインスタンスを送信されてきたデータで上書きした状態でデータベースに保存する点も CreateView にない動作となります

ですが、これらはフォームクラスのインスタンスを生成するときにデータベースから取得したインスタンスが引数に指定されるかどうかの違いであり、処理としては CreateView と共通になっています

CreateView の場合は、リクエストを受け取った際にはデータベースからのインスタンスの取得が行われません。それに対し、UpdateView の場合は、リクエストを受け取った際に、まずデータベースからのインスタンスの取得が行われることになります。

そして、UpdateView がデータベースからのインスタンスの取得を行う際には、DetailView でも定義されている get_object メソッドが実行されることになります。つまり、UpdateView でも DetailView でも同じ仕組みでデータベースからのインスタンスの取得が行われることになります。

そして、get_object メソッドでは、特定のテーブルから “プライマリーキー” や “スラッグ” によって特定される1つのインスタンスの取得が行われます。これらのプライマリーキーやスラッグは URL で指定されることになります。また、このインスタンスの取得先のテーブルはクラス変数の modelqueryset によって決まります。この辺りに関しても UpdateView と DetailView とで共通となります。

このように、UpdateViewCreateView をリクエスト受け取った際にインスタンスをデータベースから取得するように改造されたもので、そのデータベースからのインスタンスの取得の仕方は DetailView と共通になります。なので、イメージとしては UpdateView = CreateViewDetailView と考えていただいて良いと思います。

スポンサーリンク

UpdateView でのクラスベースビューの作り方

では、次は UpdateView でクラスベースビューを作成する手順について説明していきます。

UpdateView でのクラスベースビューの作り方に関しても CreateView とほぼ同様となります。

要は、views.py に UpdateView を継承するクラス(サブクラス)を定義し、views.py に定義したクラスにクラス変数やメソッドを定義することで UpdateView で定義されているクラス変数の上書きメソッドのオーバーライドを行なっていきます。これにより、UpdateView の特徴を活かしながら自身のウェブアプリに応じたビューにカスタマイズしていくことが可能となります。

クラスベースビューの作り方の説明図

また、これも CreateView と同様に、UpdateView ではリクエストに応じて get メソッドや  post メソッドが実行されるようになっており、UpdateView のクラス変数や他のメソッドは、これらの get メソッドおよび post メソッドから利用されるようになっています。したがって、UpdateView のサブクラス側でクラス変数やメソッドを上書き・オーバーライドしてやれば、この get メソッドと post メソッドの動作を変化させることができます。

UpdateViewのgetメソッドやpostメソッドからクラス変数や他のメソッドが利用される様子

クラスベースビュー作成時のポイントも CreateView と同様

また、クラスベースビュー作成時のポイントも基本的には CreateView と同様になります。CreateView でクラスベースビューを作成する際には下記の3つがポイントになります。

これらに関しても下記の CreateView の解説ページで説明していますので、詳しくは下記ページを参考にしてください(上記のリンクのジャンプ先も CreateView の解説ページに設定しています)。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現)

データベースからのインスタンスの取得は DetailView と同様

また、UpdateView では CreateView とは異なり、リクエストを受け取った際に、最初にデータベースからインスタンスの取得が行われることになります。このデータベースからのインスタンスの取得は CreateView では行われません。ただし、このインスタンスの取得は DetailView と同じ仕組みで行われ、この際には下記がポイントとなります。

これに関しては下記の DetailView の解説ページで説明していますので、詳細に関しては下記ページを参照してください(上記のリンクのジャンプ先も DetailView の解説ページに設定しています)。

DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現)

スポンサーリンク

UpdateView のクラス変数

では、次は UpdateView で定義されているクラス変数の紹介を行なっていきます。これらのクラス変数を UpdateView を継承するクラスで定義し直して上書きすることでクラスの動作のカスタマイズを行うことが可能となります。

UpdateView の場合、GET メソッドのリクエストを受け取った際に get メソッドが実行され、GET メソッドのリクエストを受け取った際に post メソッドが実行されることになるため、これらの get メソッドや post メソッドの動作を変化させることを目的にクラス変数の定義を行なっていくことになります。

ただ、ここまでも何回も説明したように、UpdateViewCreateViewDetailView を足し合わせたようなクラスであり、定義されているクラス変数は CreateViewDetailView で紹介したものと同じです(これはメソッドに関しても同じです)。

そのため、このページでは各クラス変数の詳細は解説せず、下記の CreateViewDetailView の解説ページへのリンクのみを示すようにしていきたいと思いますので、その点はご了承ください。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現) DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現)

UpdateView のクラス変数の一覧

この UpdateView で定義されるクラス変数には下記のようなものが存在します。

各リンクをクリックすれば括弧内に示した View のサブクラス の解説ページにジャンプするようにしています。基本的に、フォームを扱うための設定を行うクラス変数に関しては CreateView の解説ページ、インスタンスを1つのみ取得するための設定を行うクラス変数に関しては DetailView の解説ページ、その他のクラス変数に関しては ListView の解説ページにジャンプするようにしています。

ただし、model に関しては若干注意が必要で、CreateView の場合、この model に関しては CreateView のサブクラスで利用するフォームクラスを設定する目的で定義を行なっていました。クラス変数 fields とセットで定義する必要がありましたね! UpdateView においても同様の目的で定義されるクラス変数でもあるのですが、それと同時に UpdateView の場合はリクエストを受け取った際に取得するインスタンスの取得先のモデルクラス(テーブル)を指定する目的で定義する必要もあります。

特に、CreateView の場合、フォームクラスの指定はクラス変数 form_class の定義でも行うことができ、この場合は model の定義は不要でしたが、UpdateView の場合は、インスタンスの取得先のモデルクラスを指定するために model の定義が必要となります(model の代わりに queryset を定義しても良いです)。

UpdateView の場合は、扱うフォームクラスを指定するためのクラス変数インスタンスの取得先のモデルクラスを指定するためのクラス変数の定義が必須であることは覚えておいてください。

ちなみに、form_class を定義し、model (と queryset) を定義しなかった場合、ビューが動作する際に下記のような例外が発生することになります(CommentUpdate 部分は UpdateView のサブクラスの名称によって変わります)。

CommentUpdate is missing a QuerySet. Define CommentUpdate.model, CommentUpdate.queryset, or override CommentUpdate.get_queryset().

UpdateView のメソッド

次に UpdateView の持つメソッドを紹介していきます。UpdateView を継承したクラスを定義し、そのクラスで UpdateView の持つメソッドをオーバーライドしてやることで UpdateView とは異なる動作のクラスを実現することができるようになります。

このメソッドに関しては、解説は一覧のみの紹介のみとさせていただきたいと思います。

スポンサーリンク

UpdateView のメソッド一覧

UpdateView の持つメソッドの一覧は下記のようになります。あくまでもクラスのカスタマイズ目的でオーバーライドを行う可能性のあるものを挙げており、as_view などのカスタマイズは行わないであろうメソッドは省略しています。

また、UpdateViewget メソッドと post メソッドを持っており、メソッドが GET のリクエストを受け取った場合は get が実行され、メソッドが POST のリクエストを受け取った場合は post が実行されようになっています。そして、これらの getpost の中から各種メソッドが実行されるようになっています。

  • get:リクエストのメソッドが GET の場合の処理を実行する
  • post:リクエストのメソッドが POST の場合の処理を実行する
  • get_context_data:テンプレートに渡すコンテキストを生成する
  • get_form:フォームクラスのインスタンスを取得する
  • get_form_class:フォームクラスを取得する
  • get_form_kwargs:フォームクラスのコンストラクタに指定するパラメータを取得する
  • get_initialinitial への指定値を取得する
  • get_prefixprefix への指定値を取得する
  • form_valid:フォームから送信されてきたデータでデータベースに保存されているレコード・インスタンスを更新し、特定の URL へのリダイレクトレスポンスを返却する(妥当性の検証が OK の時に実行される)
  • form_invalid:再度フォームを表示する(妥当性の検証が NG の時に実行される)
  • get_success_url:リダイレクト先の URL を取得する
  • get_template_names:テンプレートファイルの名前を取得する
  • render_to_response:レスポンスを返却する
  • get_context_object_namecontext_object_name への指定値を取得する
  • get_queryset:インスタンスの集合(クエリセット)を取得する
  • get_object:インスタンスを取得する
  • get_slug_fieldslug_field を取得する

get メソッドと post メソッドの簡単な処理の流れは CreateView の解説ページの get メソッドの処理の流れpost メソッドの処理の流れ でそれぞれ説明していますので、これらのメソッドの処理の流れを知りたい方はリンクをクリックして解説箇所にジャンプしていただければと思います。ただし、これらのリンク先で説明しているのはあくまでも CreateView の場合の処理であって、UpdateView の場合は get メソッドや post メソッドが実行された際に最初にデータベースから更新対象のインスタンスが取得されるようになっています。

そして、ここで取得された更新対象のインスタンスがフォームクラスのコンストラクタに引数として指定されることで、更新対象のインスタンスがセットされた状態のフォームが生成され、それによって更新対象のインスタンスの情報がセットされたフォームが表示されたり、インスタンス(レコード)の更新処理が実現されるようになっていたりします。

また、特にオーバーライドする機会の多いメソッドは、これも CreateView 同様に form_validget_success_url になると思います。このオーバーライドの例に関しても CreateView の解説ページで紹介していますので、例を参考にしたい方は CreateView の解説ページを参照していただければと思います。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現)

UpdateView が生成するコンテキスト

続いて UpdateView が生成するコンテキストについて説明しておきます。

これに関しても CreateViewDetailView という考え方で良くて、UpdateView が生成するコンテキストには下記の要素が含まれます。

  • 'object' : データベースから取得されたインスタンス
  • context_object_name : データベースから取得されたインスタンス
  • 'form' : フォームクラスのインスタンス

context_object_name に関しては DetailView の解説ページの context_object_name で説明したようにクラス変数の定義で変更することも可能ですし、デフォルトは モデルクラス名 (小文字) となっています。モデルクラス名が Comment であれば 'comment' となります。

また、他のデータをコンテキストにセットしてテンプレートファイルから参照できるようにしたい場合は、ListView の解説ページの extra_context で説明しているクラス変数 extra_context を定義したり、get_context_data のオーバーライドを行なったりしてコンテキストの要素を追加する必要があります。

UpdateView の利用例

最後に、ここまでの説明のまとめとして、UpdateView を継承するクラスでのビューの作成例を示していきたいと思います。

プロジェクトとアプリの作成やモデルの定義・マイグレーションの手順に関しては下記ページの ListView の利用例 と同じとなりますので、ここでは説明を省略させていただきます。ListView の解説ページの利用例を読んでいない方は、下記ページの プロジェクトとアプリの作成モデルの作成とマイグレーション を読んで手順を進めていただければと思います。

DjangoのListViewの解説ページアイキャッチ 【Django】ListViewの使い方(クラスベースビューでの一覧リストページの実現)

スポンサーリンク

フォームの定義

プロジェクトやアプリ、モデルの準備が済んだ後は、CreateView の時同様にフォームクラスの定義を行ないます。

まず、forum フォルダの下に forms.py というファイルを新規作成し、その forms.py の中身を下記のように変更して保存してください。

forms.py
from django import forms
from .models import Comment

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['text', 'slug']

クラスベースビューの作成

続いて、このページの主題ともなっているクラスベースビューを作成していきます。今回は、ここまでの説明の通り UpdateView を継承するクラスを定義し、そのクラスをクラス変数の定義とメソッドのオーバーライドによってカスタマイズしていきます。

今回は、下記のように views.py を変更することでクラスベースビューを作成したいと思います。

views.py
from django.views.generic import  DetailView, CreateView, UpdateView
from .models import Comment
from .forms import CommentForm
from django.urls import reverse

class CommentUpdate(UpdateView):
    model = Comment
    form_class = CommentForm
    pk_url_kwarg = 'comment_id'
    template_name = 'forum/commentupdate.html'
    
    def get_success_url(self):
        return reverse('comment', kwargs={'comment_id':self.object.id})

class CommentCreate(CreateView):
    form_class = CommentForm
    template_name = 'forum/commentcreate.html'

    def get_success_url(self):
        return reverse('comment', kwargs={'comment_id':self.object.id})

class CommentDetail(DetailView):
    model = Comment
    pk_url_kwarg = 'comment_id'
    template_name_suffix = 'info'

この views.py においては3つのクラスを定義しており、1つ目は DetailView のサブクラスの CommentDetail となります。このクラスは、CommentCreateCommentUpdatepost メソッドが実行された際のリダイレクト先として利用するために定義しています。

2つ目は CreateView のサブクラスの CommentCreate になります。このクラスを利用してデータベースにインスタンスを新規登録し、そのインスタンスを CommentUpdate で更新を行うようにしていきます。

そして、3つ目が、このページの主題となっている UpdateView のサブクラスである CommentUpdate となります。クラス変数 form_class には先ほど forms.py に定義した CommentForm を指定しています。この CommentFormCommentCreate でもクラス変数 form_class に指定されていますが、別にこれらのクラスで同じフォームクラスを利用する必要はないです。新規登録時と更新時とでユーザーからの入力受付を行いたいフィールドが異なるのであれば、別のフォームクラスを指定してやるのでも良いです。また、UpdateView のサブクラスの場合はクラス変数 form_class だけでなくクラス変数 model の定義も必要である点に注意してください。

pk_url_kwarg の定義も行っていますが、この意味合いについては下記ページの pk_url_kwarg の節で解説していますので、詳しくは pk_url_kwarg  を参照していただければと思います。

DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現)

また、CommentCreate と同様に CommentUpdate でも get_success_url をオーバーライドし、インスタンスの更新後に、そのインスタンスの詳細ページ(CommentDetail で表示されるページ)を表示するようにしています。この get_success_url のオーバーライドは、下記ページの CreateView の利用例 で示したものと全く同じなので、詳細に関しては CreateView の利用例 を参照していただければと思います。

CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現)

ビューと URL とのマッピング

次は views.py で定義したビューと URL とのマッピングを行なっていきます。

まず、classviewproject フォルダの下にある urls.py を下記のように変更してください。

classviewproject/urls.py
from django.contrib import admin
from django.urls import path, include

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

続いて、forum フォルダの下に urls.py を新規作成し、中身を下記のように変更してください。

forum/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('update/<int:comment_id>/', views.CommentUpdate.as_view(), name='update'),
    path('create/', views.CommentCreate.as_view(), name='create'),
    path('comment/<int:comment_id>/', views.CommentDetail.as_view(), name='comment'),
]

このように各種 urls.py を作成しておくことで、ルートパス指定で /forum/update/<int:comment_id>/ へのリクエストがあった際に CommentUpdate が動作するようになります。この <int:comment_id> 部分には、更新対象となるインスタンスに割り当てられたプライマリーキーを指定する必要があります。そして、ここで指定されたプライマリーキーが割り当てられているインスタンスがデータベースから取得され、その後は CreateView と同様の動作でフォームの表示やデータベースへのインスタンスの保存(更新)が行われることになります。

スポンサーリンク

テンプレートの作成

次はテンプレートファイルを作成します。ソースコードの変更としては、これが最後となります。

CommentUpdate が利用するテンプレートファイル

まず、CommentUpdate ではクラス変数 template_name を定義し、template_name には 'forum/commentupdate.html' を指定しているため、CommentUpdate では “アプリ内の templates フォルダから見た相対パス” が 'forum/commentupdate.html' となるテンプレートファイルが利用されることになります。したがって、このパスにテンプレートファイルを用意しておく必要があります。

まずは、forum フォルダの中に templates フォルダを作成し、さらに templates の中に forum フォルダを作成してください。さらに、最後に作成した forum フォルダの中に commentupdate.html を新規作成し、中身を下記のように変更して保存してください。

commentupdate.html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Example of UpdateView</title>
</head>
<body>
    <main>
        <h2>コメントの修正</h2>
        <form action="{% url 'update' object.id %}" method="post">
            {% csrf_token %}
            <table>{{ form.as_table }}</table>
            <p><input type="submit" value="送信"></p>
        </form>
    </main>
</body>
</html>

このテンプレートファイルでは変数として formobject を参照しています。で、UpdateView が生成するコンテキストで説明したように、UpdateView で生成されるコンテキストには 'form' キーとしてフォームクラスのインスタンスがセットされており、テンプレートファイルに {{ form.as_table }} と記述しておくことで、そのフォームクラスに定義されているフィールドがテーブル形式で HTML に埋め込まれることになります。そして、それがページとして表示されることで、それらの入力フィールドを含むフォームが表示されることになります。

また、フォームで 送信 ボタンがクリックされた際には、下記の行によって urls.py'update' と名前を付けられた URL に object.id (プライマリーキー)がセットされた URL への POST リクエストが送信されることになります。この URL はルートパス形式で /forum/update/{object.id}/ となり、このリクエストを受け取ることで、CommentUpdate が動作してデータベースに保存されているインスタンスの更新が行われることになります。

送信ボタンクリック時に送信されるリクエスト
<form action="{% url 'update' object.id %}" method="post">

このように、DetailView 同様に、データベースから取得するインスタンスを1つに特定するための情報が URL にセットされている必要があるという点がポイントになります。そして、それを実現できるように urls.py やテンプレートファイルを実装する必要がある点が、UpdateView を使いこなす際のポイントになると思います。

CommentCreate が利用するテンプレートファイル

他のテンプレートファイルに関してはサラッと説明していきたいと思います。

まず、CommentCreate で利用されるテンプレートファイルに関しては、先ほど最後に作成した forum フォルダの下に commentcreate.html を新規作成し、中身を下記のように変更して保存してやることで準備完了となります。

commentcreate.html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Example of CreateView</title>
</head>
<body>
    <main>
        <h2>コメントの投稿</h2>
        <form action="{% url 'create' %}" method="post">
            {% csrf_token %}
            <table>{{ form.as_table }}</table>
            <p><input type="submit" value="送信"></p>
        </form>
    </main>
</body>
</html>

CommentDetail が利用するテンプレートファイル

続いて、CommentCreate で利用されるテンプレートファイルに関しては、先ほどと同様に forum フォルダの下に commentinfo.html を新規作成し、中身を下記のように変更して保存してやることで準備完了となります。

commentinfo.html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Example of DetailView</title>
</head>
<body>
    <main>
        <h2>コメント({{ comment.id }})</h2>
        <table>
            <tbody>
                <tr><td>ID   :</td><td>{{ comment.id }}</td></tr>
                <tr><td>TEXT :</td><td>{{ comment.text }}</td></tr>
                <tr><td>DATE :</td><td>{{ comment.date }}</td></tr>
                <tr><td>SLUG :</td><td>{{ comment.slug }}</td></tr>
            </tbody>
        </table>
    </main>
</body>
</html>

以上でテンプレートファイルの準備は完了となります。

動作確認

最後に動作確認を行なっておきましょう!

まずは、manage.py が存在するフォルダで下記コマンドを実行します。

% python manage.py runserver

これにより、開発用ウェブサーバーが起動しますので、ウェブブラウザから作成したアプリのページを表示することが可能となります。

次に下記 URL をウェブブラウザで表示してみてください。

http://localhost:8000/forum/create/

この URL をウェブブラウザで表示すれば下図のような textslug の入力フィールドを持つフォームが表示されるはずです。これは CommentCreate によって表示されるフォームとなります。

CommentCreateによって表示されるフォーム

表示されたフォームで適当な半角英数字の文字列を textslug に入力して 送信 ボタンを押せば、これらのフィールドに入力されたデータが対応するフィールドにセットされ、さらに id(プライマリーキー) と date(新規作成された日時)  が自動的にセットされた Comment のインスタンスがデータベースに新規登録されることになります。ただし、slug に関してはデータベースに保存されている他の Comment のインスタンスと重複していると妥当性の検証結果が NG になるようになっているので注意してください。

送信 ボタンを押してインスタンスがデータベースに新規登録されれば、リダイレクトが行われ、そのインスタンスの詳細ページに自動的に遷移するようになっているはずです。ここまでは CommentCreate の解説ページでの動作確認結果と同じです。

CommentCreateによって新規登録されたインスタンスの情報がCommentDetailによって表示される様子

続いて、下記の URL をウェブブラウザで開いてください。ただし、下記における URL の最後の 1 の部分は、先ほど新規登録したインスタンスの ID に合わせて変更するようにしてください。

http://localhost:8000/forum/update/1/

そうすれば、次は下図のようなフォームが表示されると思います。ポイントは、text フィールドと slug フィールドに、URL の最後部分で指定した ID を持つインスタンスのもの、つまり更新対象のインスタンスのフィールドにセットされている情報が表示されるという点になります。UpdateView のサブクラスの場合、こういった更新対象のインスタンスの情報がセットされた状態でフォームが表示されることになります。

CommentUpdateによって表示されるフォーム

さらに、このフォームで text フィールドと slug フィールドの値を変更したのちに 送信 ボタンをクリックしてみてください。インスタンスの新規登録時と同様にリダイレクトが行われ、コメントの詳細ページが表示されることになると思いますが、先ほど変更した値に応じて、表示される各種フィールドの値も変化していることが確認できると思います。また、ID は先ほど新規登録時に割り振られたものから変化していないため、新規登録したインスタンスそのものの更新が行われていることが確認できると思います。

CommentUpdateによって更新されたインスタンスの情報がCommentDetailによって表示される様子

CreateView の場合は、データベースへのインスタンスの保存を行うたびに新たな別のインスタンスとして新規登録されることになります。そして、新たに保存されたインスタンスには異なるプライマリーキーが割り振られることになります。それに対し、UpdateView の場合は、データベースに保存されているインスタンスを上書きする形で保存されることになります。こういった違いも、この結果から確認していただけるのではないかと思います。

まとめ

このページでは、UpdateView および UpdateView を継承したクラスベースビューの作り方について解説しました!

UpdateView はデータベースに既に保存されているインスタンス(レコード)を更新するための View のサブクラス であり、このクラスを継承することで、登録済みのユーザーの情報更新や投稿済みのコメントの修正等を行うページを簡単に実現できます。

解説の中で何回も説明しましたが、UpdateView はイメージとしては “CreateView + DetailView” であり、定義されているクラス変数やメソッドもこれらを足し合わせたものになっています。そのため、UpdateView を理解するためには、まず CreateView と DetailView について理解していただくのが良いと思います。これらが理解できれば UpdateView も使いこなせるようになると思います。

ちょっと解説が CreateView と DetailView の解説ページへのリンクばかりで分かりにくかったかもしれませんが、まずは CreateView と DetailView の解説ページを読んで UpdateView への理解を深めていただければと思います!

このサイトでは他の View のサブクラス についても説明していますので、他のページも是非読んでみてください!

DjangoのListViewの解説ページアイキャッチ 【Django】ListViewの使い方(クラスベースビューでの一覧リストページの実現) DjangoのDetailViewの解説ページアイキャッチ 【Django】DetailViewの使い方(クラスベースビューでの詳細ページの実現) CreateViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】CreateViewの使い方(クラスベースビューでの新規登録ページの実現) DeleteViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】DeleteViewの使い方(クラスベースビューでのレコード削除ページの実現) FormViewでのクラスベースビューの実現方法解説ページアイキャッチ 【Django】FormViewの使い方(クラスベースビューで汎用的なフォームを扱う) LoginViewの使い方の解説ページアイキャッチ 【Django】LoginViewの使い方(クラスベースビューでのログインの実現) LogoutViewの使い方の解説ページアイキャッチ 【Django】LogoutViewの使い方(クラスベースビューでのログアウトの実現)

同じカテゴリのページ一覧を表示