このページでは、Django フレームワークで定義される CreateView の使い方について説明していきます。
この CreateView は View というクラスのサブクラスの1つであり、ビューをクラスベースで作成する際に利用するクラスとなります。この View のサブクラス を継承し、さらにクラス変数を定義したりメソッドをオーバーライドすることで、あなたが開発したいアプリに応じたビューを作成することが可能となります。
この辺りのクラスベースビューやクラスベースビューの作り方については下記ページで解説していますので、詳しくはこちらをご参照ください。
Contents
CreateView
では、まずは CreateView について解説していきたいと思います。
レコードの新規登録を実現するクラス
CreateView は、名前の通り、データベースのテーブルへのレコードの新規登録を実現する View のサブクラス となります。Django において、データベースのテーブルはモデルクラス(モデル)であり、レコードとはモデルクラスのインスタンスとなります。したがって、CreateView は特定のモデルクラスのテーブルへのインスタンスを新規登録を実現する View のサブクラス とも言えます。
この CreateView は django.views.generic から import して利用します。
from django.views.generic import CreateView
ウェブアプリでは、データベースへのレコードの新規登録を行うものが非常に多いです。例えば、ユーザーの新規登録も、コメントの新規投稿も、レコードの新規登録によって実現されます。そして、このようなレコードの新規登録を実現するビューは、CreateView を継承することで簡単に作成することが可能です。

スポンサーリンク
GET と POST の両方のメソッドに対応するクラス
こういった、レコードの新規登録を行うような場合、フォームを表示してユーザーからの必要な情報の入力を受け付け、さらに、そのフォームから送信されてきたデータに応じたレコードをテーブルに新規登録するようなビューを作る必要があります。

CreateView においては、メソッドが GET のリクエストを受け取った時に CreateView の get メソッドが実行され、その get メソッドでフォームを表示する処理が実行されるようになっています。

また、メソッドが POST のリクエストを受け取った時には CreateView の post メソッドが実行され、その post メソッドでフォームから送信されてきたデータに応じたレコードをテーブルへ新規登録する処理が実行されるようになっています。そして、レコードの新規登録後には特定の URL へのリダイレクトレスポンスが返却されるようになっています。(フォームから送信されてきたデータが妥当でない場合には、再度フォームを表示するような処理が実行されるようにもなっています)。

CreateView を継承するクラスを定義すれば、そのクラスには上記のようなメソッドも引き継がれることになります。なので、CreateView を継承するクラスを定義することで、上記のような処理を別途実装することなく、データベースのテーブルへのレコードの新規登録を実現するビューが作成することができることになります。
また、上記のように、メソッドが GET のリクエストと POST のリクエストの両方に対応しているという点は、CreateView の特徴の1つとなります。
例えば View のサブクラス には下記ページで紹介している ListView や DetailView がありますが、これらはデータベースのレコードを表示することに特化したクラスであり、メソッドが GET のリクエストにのみ対応しています。そのため、これらの ListView や DetailView は post メソッドを持っていません。
CreateView を継承するメリット
POST にも対応し、post メソッドも定義されている分、CreateView を継承するクラスを扱うのは ListView や DetailView よりも難易度が若干高くなります。まぁ、でも、この辺りは関数ベースでビューを扱う場合も一緒だと思います。クラスベースでも関数ベースでも結局 POST に対応する分の労力が必要になります。
ですが、POST への対応に関して言えば、関数ベースビューよりもクラスベースビューの方が確実に楽に実現できると思います。関数ベースビューの場合は、関数の中でメソッドが GET であるか POST であるかを判断し、その判断結果に基づいて処理を切り変えるような実装を開発者自身が行う必要があります。
この辺りは、下記のフォームの解説ページで説明していますので、詳しく知りたい方は下記ページをご参照いただければと思います。
それに対し、クラスベースビューの場合、メソッドが GET であるか POST であるかの判断を行い、それに応じて実行する処理を切り替えるような実装が View のサブクラス で既に行われています。そして、その View のサブクラス の例の1つが、今回扱う CreateView となります。したがって、開発者は、関数ベースビューでは必要だったメソッドに応じた処理の切り替えの実装が不要となります。

つまり、次の CreateView でのクラスベースビューの作り方 で説明する手順で CreateView を継承するクラスを定義しておけば、あとはリクエストを受け取った際にリクエストに応じた処理が自動的に実行されるようになっています。そのため、CreateView を継承してクラスベースビューを作成することで処理の実装量を減らすことができますし、メソッドに応じた分岐処理等の実装も不要となるためバグも発生しにくくなります。
CreateView でのクラスベースビューの作り方
では、次はその CreateView でクラスベースビューを作成する手順について説明していきたいと思います。
CreateView でのクラスベースビューの作り方は、大まかに言えば ListView や DetailView 等の他の View のサブクラス の時と同様です。
つまり、views.py に CreateView を継承するクラスを定義し、そのクラスでクラス変数やメソッドを定義して CreateView 側で定義されているクラス変数の上書き・メソッドのオーバーライドを行なうことで、ビューを作成していきます。これにより、CreateView の特徴を活かしながら自身のウェブアプリに応じたビューにカスタマイズしていくことが可能となります。

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

これらの get メソッドや post メソッドの動作を変化させ、開発するウェブアプリに適したビューに仕立てるために、CreateView を継承するクラスでのクラス変数やメソッドの定義が必要となります。
スポンサーリンク
利用するフォームを設定する
この CreateView でクラスベースビューを作成する場合にポイントになるのがクラス変数の定義によるフォームクラスの設定になります。
CreateView にはフォームが必要
まず、インスタンスの新規登録を実現するためには、get メソッドが実行された際に新規登録するインスタンス(レコード)の情報の入力・送信を受け付けるためのフォームを表示する必要があります。そして、このフォームはフォームクラスのインスタンスを HTML に要素として埋め込むことで表示されるようになっており、そのインスタンスのクラスを CreateView を継承するクラス側で設定しておく必要があります。

また、post メソッド実行時にもフォームクラスのインスタンスが必要となります。そのため、そのインスタンスの基になるフォームクラスを CreateView を継承するクラス側で設定しておく必要があります。
具体的にいうと、post メソッド実行時はフォームから送信されてきたデータを受け取り、そのデータからフォームクラスのインスタンスが生成されます。そして、このインスタンスに is_valid メソッドを実行させることで、送信されてきたデータの妥当性の検証が行われます。さらに、妥当性の検証結果が OK の場合は、そのインスタンスに save メソッドを実行させることで、送信されてきたデータがレコードとしてデータベースへ新規登録されることになります。

CreateView が利用するフォームは『モデルフォーム』
ここでポイントになるのがフォームクラスのインスタンスの save メソッドが実行されるという点になります。通常のフォームクラスには save メソッドが存在しないため、CreateView を継承するクラスで利用するのは単なるフォームクラスではなくモデルフォームクラスである必要があることになります。下記ページでも解説しているとおり、モデルフォームクラスは model に指定したモデルクラスに基づいて生成されるクラスであり、このクラスのインスタンスに save メソッドを実行させれば、その model に指定したモデルクラスのテーブルにレコード保存されることになります。
ここで覚えておいていただきたいのは、データベースへの新規登録を行うためには、新規登録先のテーブルを指定する必要があり、それを決めるのがモデルフォームクラスになるという点になります。
post メソッド実行時の動作の説明に戻ると、post メソッドから妥当性の検証が行われて検証結果が NG の場合は、フォームクラスのインスタンスを再度 HTML に埋め込んだものをレスポンスとしてクライアントに返却することで、クライアント側で再度フォームの表示及び入力の再受付が行われるようになっています。

このような動作はフォームを扱う上での典型的な処理の流れとなっており、先ほども紹介した下記ページのフォームの解説ページでも詳しく説明していますので、復習したい方は是非下記ページを読んでみてください。
このように、CreateView および CreateViewのサブクラスでは多くの場面でフォームクラスが利用されることになり、CreateView のサブクラスを定義する際にはフォームクラスの設定が非常に重要となります。
CreateView が利用するフォームは form_class で指定可能
そして、CreateView のサブクラスで利用するフォームクラスは、下記のクラス変数を定義することで設定することができます。
- クラス変数
form_classを定義する - クラス変数
modelとfieldsを定義する
前者に関しては分かりやすくて、クラス変数 form_class を定義して CreateView のサブクラスで利用するフォームクラスを直接指定する実現方法になります。クラス変数 form_class を定義することで、form_class に指定したフォームクラスが CreateView のサブクラスから利用されるようになり、そのクラスのインスタンスがフォーム要素としてページに表示されたりデータベースへの保存を行なったりするようになります。
前述の通り、form_class にはモデルフォームクラスを指定する必要があります。モデルフォームクラスに関しては下記ページで解説していますので、モデルフォームクラスをご存知ない方は下記ページを参照してください。要は、モデルクラスに基づいて自動的に生成されるフォームクラスがモデルフォームクラスとなります。
CreateView が利用するフォームは model & fields で指定可能
後者に関しては、CreateView の中で model で指定されたモデルクラスと fields で指定されたフィールドに基づいて新たにモデルフォームクラスを生成させ、そのフォームクラスを利用するように設定する実現方法になります。
model には新規登録したいインスタンス(レコード)のモデルクラスを指定し、fields にはフォームで扱いたいフィールドをリスト形式やタプル形式で指定します。この fields に指定するリストやタプルの要素は model に指定したモデルクラスの持つフィールドである必要があります。このようにクラス変数を定義することで、CreateView の get メソッドや post メソッドが実行される際には、fields に指定したリストやタプルに含まれるフィールドのみを持つモデルフォームクラスが生成されることになります。そして、それを利用して get メソッドや post メソッドが動作することになります。

前者と後者のどちらの方法を採用しても CreateView のサブクラスはうまく動作させられることになりますが、モデルフォームクラスを定義しているのであれば前者の方法を、それ以外は後者の方法を採用するので良いと思います。
いずれにしても、この利用するフォームを設定する必要がある点は CreateView のサブクラスを使いこなす上で重要となりますので、是非この点は覚えておいてください。
リダイレクト先の URL を設定する
また、CreateView でクラスベースビューを作成する上ではリダイレクト先の URL の設定も必要となります。
CreateView ではフォームから送信されてきたデータに対して妥当性の検証が行われ、検証結果が OK の場合には送信されてきたデータがレコード(インスタンス)としてデータベースに保存されることになります。そして、保存完了後は他の URL へのリダイレクトが行われることになります。で、この時に、どの URL にリダイレクトするのかをクラス変数として定義しておく必要があります。もしくは、リダイレクト先の URL を返却するようなメソッドを定義しておく必要があります。これらが定義されていない場合は、下記のような例外が発生することになります。
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
このような例外の発生は下記の3つの方法により回避することができます。
CreateViewのサブクラスにクラス変数success_urlを定義するCreateViewのサブクラスにメソッドget_success_urlを定義するCreateViewのサブクラスのmodel等で指定したモデルクラスにメソッドget_absolute_urlを定義する
リダイレクト先の URL が静的に決まるのであれば、1つ目の方法(クラス変数を定義する方法)でリダイレクト先の URL を指定するようにしてやれば良いです。リダイレクト先の URL が静的に決まらないのであれば、つまり状況やタイミング等に応じてリダイレクト先の URL を動的に決めたいのであれば、2つ目 or 3つ目の方法(メソッドを定義する方法)でリダイレクト先の URL を取得できるようにする必要があります。
例えば、ユーザーの新規登録後に、そのユーザーのマイページにリダイレクトさせたいのであれば、新規登録されるユーザーのマイページの URL が新規登録されたユーザーに応じて変化することになるため、後者の方法でリダイレクト先の URL を取得できるようにする必要があります。

ですが、ユーザーの新規登録後にユーザー一覧の表示ページにリダイレクトさせたいのであれば、ユーザー一覧の表示ページの URL は常に同じはずなので、前者の方法でリダイレクト先の URL を指定してやれば良いです。

CreateView でクラスベースビューを作成する上では、インスタンス(レコード)の保存後にリダイレクトが行われることと、そのリダイレクト先の URL が指定できるようにクラス変数やメソッドの定義が必要であることは覚えておいてください。
妥当性の検証結果が OK の場合の処理を変更する
また、CreateView のサブクラスでは、フォームから送信されてきたデータの妥当性の検証結果が OK の場合に実行する処理をメソッドのオーバーライドによって変更可能であることも覚えておくと良いと思います。
CreateView では、フォームから送信されてきたデータの妥当性の検証結果が OK の場合に form_valid というメソッドが実行されるようになっています。この form_valid では、送信されてきたデータのレコードとしてのデータベースへの保存と前述のリダイレクトが行われるようになっています。逆に言えば、これらしか行われないようになっています。
ですが、このメソッドを CreateView のサブクラスに定義することでオーバーライドすることができ、妥当性の検証結果が OK の場合に実行する処理を追加したり変更したりすることが可能となります。
例えば、ログイン機能を備えたウェブアプリの場合、ユーザー登録後(ユーザーのインスタンスのデータベースへの新規登録後)にログイン処理も合わせて行いたいようなことがあります。このログイン処理の追加も、CreateView のサブクラスで form_valid をオーバーライドし、その form_valid の中でログイン処理を実行するようにすることで実現可能となります。
同様に、妥当性の検証結果が NG の場合には form_invalid が実行されるようになっているため、妥当性の検証結果が NG の場合の処理の追加や変更に関しても form_invalid のオーバーライドにより実現することができます。
とりあえず、CreateView でクラスベースビューを作成するのであれば、『利用するフォームクラスの設定方法』、『リダイレクト先の設定方法』、『妥当性の検証結果が OK の場合に実行する処理の変更方法』に関しては覚えておいた方が良いと思います。逆に、この辺りさえしっかり理解しておけば、CreateView でのクラスベースビューの作成には困らないと思います。
ただ、上記で紹介したクラス変数やメソッド以外のものも CreateView で定義されており、それらを CreateView を継承するクラスで定義することで、より細かなビューの設定を行うことも可能です。
ここからは、それらの CreateView で定義されているクラス変数やメソッドの詳細の紹介を行っていきたいと思います。
スポンサーリンク
CreateView のクラス変数
では、次は CreateView で定義されているクラス変数の紹介を行なっていきます。これらのクラス変数を CreateView を継承するクラスで定義し直して上書きすることでクラスの動作のカスタマイズを行うことが可能となります。
CreateView の場合、GET メソッドのリクエストを受け取った際に get メソッドが実行され、GET メソッドのリクエストを受け取った際に post メソッドが実行されることになるため、これらの get メソッドや post メソッドの動作を変化させることを目的にクラス変数の定義を行なっていくことになります。
CreateView のクラス変数の一覧
その CreateView で定義されるクラス変数には下記のようなものが存在します。
- form_class
- success_url
- model
- fields
- initial
- prefix
- template_name
- template_name_suffix
- extra_context
- template_engine
- response_class
- content_type
extra_context・template_engine・response_class・content_type に関しては ListView のクラス変数の役割と全く同じなので、詳しくは ListView の解説ページを参照していただければと思います(これら4つの各リンクには ListView の解説ページでの説明部分へのリンクを設定しています)。
また、これらが CreateView で定義されているクラス変数の全てというわけではないので注意してください。定義はされているものの CreateView では基本的に使用しないクラス変数は省き、さらにカスタマイズに利用する機会の多そうなもののみを紹介しています。全てのクラス変数を知りたい場合は、実際に CreateView の定義をソースコードで確認していただくのが一番早いと思います。
また、ここからは、アプリの models.py で下記のような Comment が定義されていることを、前提に解説を行なっていきます。
from django.db import models
class Comment(models.Model):
text = models.CharField(max_length=256)
date = models.DateField(auto_now_add=True)
slug = models.SlugField(max_length=256, null=True, unique=True)
さらに、アプリの forms.py で下記のような CreateCommentForm が定義されていることを、前提に解説を行なっていきます。
from django import forms
from .models import Comment
class CreateCommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['text', 'slug']
slug フィールドの役割や意味合いについては下記の DetailView の解説ページの中で説明していますので、必要に応じて下記ページを参照していただければと思います。
では、先ほど挙げたクラス変数の役割や、これらを定義することで実現できることについて、1つ1つ説明していきます。
form_class
最初に紹介するクラス変数が form_class で、CreateView でクラスベースビューを作成していく上で一番のポイントになるのが、この form_class になると思います。
この form_class はビューで扱うフォームクラスを指定するクラス変数になります。利用するフォームを設定する でも説明したように、form_class には単なるフォームクラスではなくモデルフォームクラスを指定します。
また、form_class で指定したフォームクラスは、これも 利用するフォームを設定する で説明したように、フォームを表示する際やフォームから送信されてきたデータをインスタンスとしてデータベースに保存するときなど、様々な場面で利用されることになります。
例えば、下記のように CommentCreate を定義すれば、CommentCreate の get メソッドや post メソッド実行時に CreateCommentForm が利用されるようになります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
form_class = CreateCommentForm
CreateView のサブクラスにおいては、この form_class、もしくは、後述で紹介する model & fields の定義が必須となります。
スポンサーリンク
success_url
前述の通り、CreateView は post メソッドを持っており、post メソッド実行時にはフォームから送信されてきたデータのレコード(インスタンス)としてのデータベースへの保存が行われ、その後に特定の URL にリダイレクトをするようになっています(リダイレクトのレスポンスを返却する)。
success_url は、この時のリダイレクト先の URL を指定するためのクラス変数となります。
例えば、下記のように CommentCreate を定義すれば、CommentCreate の post メソッドが実行されてデータベースへのインスタンスの保存が行われた後に 'comments' という名前が付けられた URL にリダイレクトされるようになります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
from django.urls import reverse_lazy
class CommentCreate(CreateView):
form_class = CreateCommentForm
success_url = reverse_lazy('comments')
ウェブアプリがリクエストを受け付ける URL に対しては urls.py によって名前をつけることができます。そして、その名前から URL に変換するのが、上記で利用している reverse_lazy となります。
reverse_lazy については下記ページで解説していますので、詳しくは下記ページをご参照ください。success_url に URL を指定する際には reverse ではなく reverse_lazy を利用する必要がある点がポイントとなります。
また、クラス変数 success_url に指定できるのは静的な URL のみとなります。状況に応じてリダイレクト先の URL を動的に変化させたいような場合は get_success_url メソッドのオーバーライドを行う or モデルクラスに get_absolute_url を定義する必要があります。この詳細については、後述の get_success_url で説明します。
model
また、利用するフォームを設定する で説明したように、クラス変数 form_class を定義するのではなく、ここで説明する model と次に説明する fields をクラス変数として定義することでも CreateView のサブクラスが利用するフォームを設定することが可能です。
クラス変数 form_class を指定した場合は、form_class で指定されたクラスがフォームとして利用されることになります。それに対し、model と fields を指定した場合は、これらにセットされたモデルクラスとフィールドからフォームクラスオブジェクトが生成され、それがフォームとして利用されることになります。
ListView や DetailView ではインスタンスの取得先のテーブルを指定するために model を定義しましたが、CreateView の場合はインスタンスの取得先のテーブルを指定するのではなく、form_class が定義されていない場合に利用するフォームを生成するために定義することになります。また、後述でも説明しますが、クラス変数 template_name を定義しない場合も、この model の定義が必要になります。
逆に言えば、form_class と template_name の両方が定義されているのであれば、model の定義はあってもなくても良いです。
詳細な説明は省略しますが、model の代わりに queryset を定義することも可能です
クエリには操作対象となるテーブル(モデルクラス)の情報が含まれており、その情報から特定したモデルクラスが model の代わり利用されることになります
例えば、Comment の持つフィールドに応じたフォームを CreateView を継承するクラスから利用するようにしたいのであれば、下記のように model を定義してやれば良いことになります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
ただし、単に上記のように model を定義しただけだと次のような例外が発生することになります。
Using ModelFormMixin (base class of CommentCreate) without the 'fields' attribute is prohibited.
この例外のメッセージからも分かるように、クラス変数 model だけでなくクラス変数 fields も一緒に定義してやれば、この例外は解決することができます。
つまり、CreateView のサブクラスにおいて、扱うフォームをクラス変数 form_class ではなくクラス変数 model で設定する場合はクラス変数 fields の定義が必須となります。
fields
では、続いては、その fields について説明していきます。
fields は、フォームに表示するフィールドを指定するクラス変数となります。違う言い方をすれば、ユーザーからの値の入力の受付を行うフィールドを指定するクラス変数となります。model に指定するのはモデルクラスで、このモデルクラスはデータベースのテーブルにあたり、このテーブルは models.py でのモデルクラスの定義に基づいてフィールド(カラム)を持つことになります。
fields は、このテーブルのフィールドの中のどれをフォームのフィールドとして扱うのかを指定するクラス変数となります。

そして、model と fields を定義しておけば、利用するフォームを設定する で説明したように、これらによって指定されたフィールドの入力受付を行うフォーム(モデルフォームクラス)が定義され、そのフォームが CreateView のサブクラスで扱われるようになります。
例えば下記のように CommentCreate を定義すれば、Comment の text とslug をフィールドとして持つモデルフォームクラスが生成され、それを CommentCreate が利用するようになります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
fields = ['text', 'slug']
したがって、CommentCreate でフォームを表示する際には、下の図のように text と slug の入力受付を行うフォームが表示されるようになります。

このフォームの表示を行うためにはテンプレートファイルの用意であったり、利用するテンプレートファイルを指定するクラス変数の定義が必要となります。この辺りは後述で解説していきます。
前述の通り、model と fields はセットで定義する必要があります。逆に、form_class を定義する場合には fields の定義は禁止されており form_class と fields の両方をクラス変数として定義すると下記のような例外が発生することになるので注意してください。この場合は fields の定義を削除してやれば例外を解消することができます。
Specifying both 'fields' and 'form_class' is not permitted.
スポンサーリンク
initial
initial はフォームの各種フィールドの初期値を指定するクラス変数となります。このクラス変数 initial には、下記のように辞書形式のデータを指定する必要があります。
initial = {
'フィールド1のフィールド名': フィールド1の初期値,
'フィールド2のフィールド名'; フィールド2の初期値
}
クラス変数 initial でフォームの各種フィールドに初期値を指定しておけば、フォームが表示された際に、各種フィールドに初期値に指定した値が表示されるようになります。
例えば下記のように CreateView を定義すれば、クラス変数 initial により、GET メソッドのリクエストによってフォームが表示される際に text フィールドには hello という文字列が入力された状態で表示されることになります。それに対し slug フィールドには初期値を指定していないため、slug フィールドは空白の状態で表示されることになります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
fields = ['text', 'slug']
initial = {
'text': 'hello'
}
実際のフォームの表示結果は下記のようなものになります。

prefix
prefix は各種フィールドのタグの属性に指定する文字列に接頭辞を付加するためのクラス変数となります。
例えば、先ほどの initial の説明の中で示した CommentCreate の例の場合、生成される HTML において、フォームの中の text フィールドと slug フィールドのタグは下記のようなものになります。
<tr>
<th><label for="id_text">Text:</label></th>
<td>
<input type="text" name="text" value="hello" maxlength="256" required id="id_text">
</td>
</tr>
<tr>
<th><label for="id_slug">Slug:</label></th>
<td>
<input type="text" name="slug" maxlength="256" required id="id_slug">
</td>
</tr>
それに対し、下記のようにクラス変数 prefix を定義した場合、
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
fields = ['text', 'slug']
initial = {
'text': 'hello'
}
prefix = 'comment'
生成される HTML において、フォームの中の text フィールドと slug フィールドのタグは下記のようなものに変化します。ところどころ、属性に指定される文字列に prefix に指定した comment が付加されていることが確認できると思います。一部接頭辞ではないものもありますが…。まぁとりあえず、こんな感じで各属性への指定値に特定の文字列を追加で付加するためのクラス変数が prefix となります。
<tr>
<th><label for="id_comment-text">Text:</label></th>
<td>
<input type="text" name="comment-text" value="hello" maxlength="256" required id="id_comment-text">
</td>
</tr>
<tr>
<th><label for="id_comment-slug">Slug:</label></th>
<td>
<input type="text" name="comment-slug" maxlength="256" required id="id_comment-slug">
</td>
</tr>
template_name
ここからは、テンプレートファイルに関するクラス変数について説明していきます。CreateView の場合、GET メソッドのリクエストを受け取ってフォームを表示する際にテンプレートファイルが利用されます。

また、POST メソッドのリクエストを受け取った場合でも、フォームから送信されてきたデータの妥当性の検証の検証結果が NG の場合には再度フォームを表示することになるため、その際にもテンプレートファイルが利用されることになります。

こういったページの表示を行う際に利用するテンプレートファイルのパスを指定するのがクラス変数 template_name となります。このパスには、アプリの templates フォルダから見た相対パスを指定します。
デフォルトでは、テンプレートファイルのパスとして アプリ名/モデルクラス名_form.html が設定されるようになっているため、CreateView を継承するクラスが動作する際は、あらかじめこのパスにテンプレートファイルを用意しておくか、template_name を定義して template_name に指定したパスにテンプレートファイルを用意しておく必要があります。
例えば、forum というアプリの views.py で下記のように CommentCreate を定義した場合、テンプレートファイルは forum/templates/forum/create.html に用意しておく必要があります。
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
form_class = CreateCommentForm
template_name = 'forum/create.html'
また、これに関しては後述の CreateView が生成するコンテキスト で説明しますが、CreateView が生成するコンテキストには form キーに form_class で指定したフォームクラスのインスタンス or model + fields から生成されるクラスのインスタンスがセットされることになるため、用意するテンプレートファイルでは form 変数をフォームとして出力するようにしておく必要があります。

template_name を指定しない場合は、クラス変数 model の定義が必須となるという点に注意してください。template_name を指定しない場合は、前述のとおり アプリ名/モデルクラス名_form.html がテンプレートファイルのパスとなるのですが、この モデルクラス名 部分は、クラス変数 model に指定したモデルクラスのクラス名を小文字に変換したものとなります。したがって、クラス変数 template_name とクラス変数 model の両方を定義していない場合、テンプレートファイルのパスが定まらなくなり、下記のような例外が発生することになります。
TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
このような例外が発生したら、クラス変数 model or クラス変数 template_name を定義して例外を解消するようにしてください。
スポンサーリンク
template_name_suffix
先ほど template_name を定義しなかった場合、テンプレートファイルのパスとして アプリ名/モデルクラス名_form.html がデフォルトで設定されると言いましたが、この _form 部分はクラス変数 template_name_suffix を定義して変更することも可能です。
template_name_suffix は、その名の通りデフォルトのテンプレートファイルのパスにおけるファイル名の末尾を指定するクラス変数であり、CreateView の場合はデフォルトで '_form' が指定されています。
例えば、forum というアプリの views.py で下記のように CommentCreate を定義した場合、
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
fields = ['text', 'slug']
template_name を指定していないため、デフォルト設定のテンプレートファイルが利用されることになり、そのファイルのパスは forum/comment_form.html となりますので、このパスにテンプレートファイルを用意しておく必要があることになります。
それに対し、下記のように CommentCreate を定義した場合、
from django.views.generic import CreateView
from .models import Comment
from .forms import CreateCommentForm
class CommentCreate(CreateView):
model = Comment
fields = ['text', 'slug']
template_name_suffix = '_create'
デフォルト設定のテンプレートファイルが利用されるという点は先ほどと同じですが、template_name_suffix に '_create' を指定しているため、利用されるテンプレートファイルのパスは forum/comment_create.html となります。
CreateView のメソッド
次に CreateView の持つメソッドを紹介していきます。CreateView を継承したクラスを定義し、そのクラスで CreateView の持つメソッドをオーバーライドしてやることで CreateView とは異なる動作のクラスを実現することができるようになります。
まずはメソッド一覧を示し、続いて、その中からオーバーライドする機会が多そうなメソッドのみの詳細を説明するようにしたいと思います。
CreateView のメソッド一覧
CreateView の持つメソッドの一覧は下記のようになります。あくまでもクラスのカスタマイズ目的でオーバーライドを行う可能性のあるものを挙げており、as_view などのカスタマイズは行わないであろうメソッドは省略しています。
また、CreateView は get メソッドと post メソッドを持っており、メソッドが GET のリクエストを受け取った場合は get が実行され、メソッドが POST のリクエストを受け取った場合は post が実行されようになっています。そして、これらの get や post の中から各種メソッドが実行されるようになっています。
get:リクエストのメソッドがGETの場合の処理を実行するpost:リクエストのメソッドがPOSTの場合の処理を実行するget_context_data:テンプレートに渡すコンテキストを生成するget_form:フォームクラスのインスタンスを取得するget_form_class:フォームクラスを取得するget_form_kwargs:フォームクラスのコンストラクタに指定するパラメータを取得するget_initial:initialへの指定値を取得するget_prefix:prefixへの指定値を取得するform_valid:フォームから送信されてきたデータをデータベースに保存して特定の URL へのリダイレクトレスポンスを返却する(妥当性の検証が OK の時に実行される)form_invalid:再度フォームを表示する(妥当性の検証が NG の時に実行される)get_success_url:リダイレクト先の URL を取得するget_template_names:テンプレートファイルの名前を取得するrender_to_response:レスポンスを返却する
get メソッドの処理の流れ
get メソッドと post メソッドの処理について簡単に説明しておくと、まず get では get_context_data メソッドが呼び出され、このメソッドの中でフォームクラスのインスタンスが生成され、それがコンテキストの 'form' キーに値としてセットされることになります。さらに、このフォームクラスのインスタンスの生成は、get_context_data メソッドから呼び出しされる get_form メソッドで実施されるようになっています。
そして、この get_form メソッドからは最初に get_form_class が呼び出され、クラス変数 form_class で指定されたクラス or model + fields によって生成されるクラスが取得されます。さらに、get_form_kwargs で、それらのクラスのコンストラクタに指定するキーワード引数が取得されます。この中でクラス変数 initial やクラス変数 prefix が取得され、それがキーワード引数に指定された状態でコンストラクタが実行されることで、これらのクラス変数への指定値が反映された状態のフォームクラスのインスタンスが生成されることになります。
そして、前述のとおり、このフォームクラスのインスタンスがコンテキストの 'form' キーに値としてセットされます。コンテキスト生成後には render_to_response メソッドが実行され、コンテキストとテンプレートファイルに基づいて HTML が生成されてレスポンスとして返却されることになります。
ちなみに、下記ページで紹介している “インスタンスの更新を行う View のサブクラス” である UpdateView においては、前述の get_form_kwargs で事前にデータベースから取得した更新対象のインスタンスが 'instance' キーにセットされた辞書が取得されるようになっています。そして、それを引数としてコンストラクタが実行されてフォームクラスのインスタンスが生成されることになります。
したがって、UpdateView では get メソッド実行時に事前に取得されたインスタンスの情報が各種フィールドにセットされた状態でフォームが表示されることになりますし、後述の post メソッド実行時には事前に取得されたインスタンスをフォームから送信されてきたデータで上書きしたものがデータベースに保存されるようになっています。
こういった違いはあるものの、基本的には、UpdateView と CreateView では事前にインスタンスをデータベースから取得するかどうかと、get_form_kwargs が返却する辞書に事前に取得したインスタンスがセットされているかどうかの違いしかありません。そのため、CreateView をしっかり理解しておけば UpdateView も簡単に使いこなすことができます!
post メソッドの処理の流れ
また、post メソッドでは、まず get_form メソッドが実行されてフォームのインスタンスの生成が行われます。このフォームのインスタンスがコンストラクタで生成される際にはコンストラクタの引数にフォームから送信されてきたデータが指定されることになるため、各種フィールドにフォームから送信されてきたデータがセットされた状態のインスタンスが生成されることになります。
さらに、生成されたインスタンスに is_valid メソッドを実行させることで、送信されてきたデータの妥当性の検証が行われます。この is_valid メソッドはモデルフォームクラスの持つメソッドになります。
妥当性の検証結果が OK の場合は form_valid メソッドが実行されます。form_valid メソッドでは、まずモデルフォームクラスのインスタンスから save メソッドが実行され、送信されてきたデータがレコードとしてデータベースに保存されることになります。そして、get_success_url メソッドが返却する URL に対するリダイレクトレスポンスが生成されて返却されることになります。get_success_url メソッドではクラス変数 success_url が定義されている場合はそれが返却され、それ以外の場合は、保存されたレコード(インスタンス)から get_absolute_method が実行されるようになっており、このメソッドの返却値がリダイレクト先の URL として返却されることになります。
妥当性の検証結果が NG の場合は form_invalid メソッドが実行され、この場合は get メソッドの時と同様に HTML が生成されてレスポンスとして返却されることになります。ただし、コンテキストの 'form' キーに値としてセットされるフォームクラスのインスタンスには、フォームから送信されてきた各種フィールドのデータおよび妥当性の検証結果が NG となった理由を示すエラーメッセージがセットされた状態となっているため、このインスタンスをフォームとして表示した際には、各種フィールドにユーザーが前回入力したデータがセットされた状態で、さらにはエラーメッセージを含む状態でフォームが表示されることになります。
この辺りの妥当性の検証であったり、妥当性の検証結果が NG となった場合のフォームの際表示に関しては下記ページで詳しく説明していますので、必要に応じて参照していただければと思います。
簡単に説明させていただきましたが、get メソッドや post メソッドでは上記のような流れで処理が行われており、その中で様々なメソッドの実行やクラス変数の参照が行われるようになっています。
これらのメソッドの中で、特にオーバーライドする機会が多くなるのは form_valid と get_success_url になると思います。この2つについて詳細を説明していきたいと思います。
スポンサーリンク
form_valid
まず form_valid について説明していきます。
この form_valid に関しては 妥当性の検証結果が OK の場合の処理を変更する で説明した通りで、フォームから送信されてきたデータの妥当性の検証結果が OK である場合に実行されるメソッドになります。そして、このメソッド内部ではフォームから送信されてきたデータをレコードとしてテーブルに保存し(新規登録)、さらに特定の URL にリダイレクトするためのレスポンスを返却する処理が行われるようになっています。そのため、これ以外の処理を form_valid で実施するようにしたいのであれば、form_valid のオーバーライドが必要になります。
例えば下記は、【Django入門14】クラスベースビューの基本 の 掲示板アプリのビューをクラスベースに変更する で紹介した form_valid のオーバーライドの例になります。下記の通り、form_valid は第1引数を self、第2引数を form として定義する必要があります。
下記のように form_valid を定義してオーバーライドしてやれば、スーパークラスの form_valid、つまり CreateViewの form_valid が実行されてテーブルへのレコードの新規登録とリダイレクトのレスポンスの生成が行われた後に login が実行され、ここでログイン処理が行われることになります。
class Register(CreateView):
model = User
form_class = RegisterForm
template_name = 'forum/register.html'
def form_valid(self, form):
response = super().form_valid(form)
user = self.object
login(self.request, user)
return response
レコードの新規登録の後に追加で処理を行いたいことも多いので、そういったことが form_valid のオーバーライドによって実現可能であることは是非覚えておいてください。
ただし、form_valid は基本的にリダイレクトのレスポンスを返却する必要があるという点には注意してください。CreateViewの form_valid の返却値もリダイレクトのレスポンスとなりますので、基本的には、その返却値をオーバーライドした側の form_valid でも返却するようにしてやれば良いです。上記においては return response の部分がそれにあたります。
また、フォームから送信されてきたデータの妥当性の検証結果が NG の場合は form_invalid メソッドが実行されるようになっているため、この場合の動作を変更したい場合は、ここで紹介した form_valid と同様に form_invalid のオーバーライドを行うようにしましょう。
get_success_url
次は get_success_url のオーバーライドの例を紹介していきます。
get_success_url はリダイレクト先の URL を取得するメソッドで、このメソッドは先ほど説明した form_valid から呼び出されるようになっています。
この get_success_url は、クラス変数 success_url が定義されている場合は、その success_url に指定されている URL が返却されるようになっています。クラス変数 success_url が定義されていない場合は、インスタンスの保存先となるモデルクラス(テーブル)の get_absolute_url メソッドの返却値が返却されることになるのですが、この get_absolute_url メソッドがモデルクラスに定義されていない場合は下記の例外が発生することになります。なので get_success_url メソッドをそのまま利用する場合は、クラス変数 success_url を定義する or モデルクラス側で get_absolute_url メソッドを定義することが必須となります。
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
リダイレクト先の URL を設定する でも解説した通り、静的に決まる URL であれば、クラス変数を定義し、動的に決める必要のある URL であれば、メソッドを定義するので良いと思います。モデルクラス側に get_absolute_url を定義して動的にリダイレクト先の URL 返却する例に関しては、後述の CreateView の利用例 で紹介します。
もしくは、get_success_url メソッドをオーバーライドしてしまって上記のような作りから根本的に変更してしまうという手もあります。
例えば下記は、【Django入門14】クラスベースビューの基本 の 掲示板アプリのビューをクラスベースに変更する で紹介した get_success_url のオーバーライドの例になります。
下記のように get_success_url を定義してオーバーライドしてやれば、post メソッドからは CreateView の get_success_url ではなく、Register の get_success_url が呼び出されるようになります。
class Register(CreateView):
model = User
form_class = RegisterForm
template_name = 'forum/register.html'
def get_success_url(self):
return reverse('user', kwargs={'user_id':self.object.pk})
この get_success_url メソッドでは、クラス変数 success_url も参照していませんし、get_absolute_url メソッドも呼び出していないため、両方が定義されていなくても例外が発生しません。また、get_success_url メソッドでは、self.object から事前にテーブルに新規登録されたインスタンスを取得することができます。なので、get_success_url メソッドの中で self.object を参照することで、テーブルに新規登録されたインスタンスに応じて動的に生成した URL を返却するようなことが可能となります。
ちなみに、上記の get_success_url では、urls.py で 'user' と名付けられた URL の後ろに self.object.pk (新規登録されたインスタンスのプライマリーキー) が追加された URL が返却されることになります。
CreateView を継承するクラスを利用する上では、レコードの新規登録後のリダイレクト先の URL も重要であり、この URL の決め方には下記の3つが存在することは覚えておきましょう!
CreateViewのサブクラスにクラス変数success_urlを定義するCreateViewのサブクラスにメソッドget_success_urlを定義するCreateViewのサブクラスのmodel等で指定したモデルクラスにメソッドget_absolute_urlを定義する
CreateView が生成するコンテキスト
続いて CreateView が生成するコンテキストについて説明しておきます。
CreateView では、コンテキストは GET メソッドのリクエストを受け取って get メソッドが実行された時、もしくは、POST メソッドのリクエストを受け取って post メソッドが実行されたけど妥当性の検証結果が NG であった時に生成されます(フォームを再表示するため)。
そして、CreateView が生成するコンテキストには下記の要素が含まれます。見ての通り、基本的に CreateView が生成するコンテキストは 'form' キーのみを持つことになります。
'form': フォームクラスのインスタンス
このようなコンテキストを利用したテンプレートファイルからのフォームの表示の仕方の詳細については下記ページの フォームの表示 の節を参照していただければと思います。
また、他のデータをテンプレートファイルから参照したい場合は、extra_context で説明しているクラス変数 extra_context を定義したり、get_context_data のオーバーライドを行なったりしてコンテキストの要素を追加する必要があります。
スポンサーリンク
CreateView の利用例
最後に、ここまでの説明のまとめとして、CreateView を継承するクラスでのビューの作成例を示していきたいと思います。
プロジェクトとアプリの作成やモデルクラスの定義・マイグレーションの手順に関しては下記ページの ListView の利用例 と同じとなりますので、ここでは説明を省略させていただきます。ListView の解説ページの利用例を読んでいない方は、下記ページの プロジェクトとアプリの作成 と モデルの作成とマイグレーション を読んで手順を進めていただければと思います。
フォームの定義
プロジェクトやアプリ、モデルクラスの準備が済んだ後は、モデルフォームクラスの定義を行なっていきたいと思います。CreateView のサブクラスでクラス変数 model と fields の定義を行なっておけばモデルフォームクラスは必須ではないのですが、今回の例ではモデルフォームクラスを定義し、そのフォームクラスを CreateView のサブクラスで利用するようにしていきたいと思います。
ということで、forms.py を作成し、そこにモデルフォームクラスの定義を行なっていきたいと思います。まず、forum フォルダの下に forms.py というファイルを新規作成し、その forms.py の中身を下記のように変更して保存してください。
from django import forms
from .models import Comment
class CreateCommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['text', 'slug']
この CreateCommentForm の model には Comment を定義しているため、Comment モデルクラスに基づいたフォームクラスが定義されることになります。したがって、この CreateCommentForm のインスタンスから save メソッドを実行させた場合は、Comment モデルクラスの save メソッドが実行されて Comment モデルクラスのインスタンスがレコードとしてデータベースに保存されることになります。そして、この CreateCommentForm のインスタンスからの save メソッドの実行は、次に説明する CommentCreate (CreateView) の form_valid から行われるようになっています。

さらに fields = ['text', 'slug'] を指定しているため、フォームクラスのインスタンスを表示した際には、Comment モデルクラスに定義されているフィールドのうち、text と slug のみの入力受付を行うフォームが表示されることになります。
こんな感じで、モデルクラスに基づいたフォームクラスがモデルフォームクラスとなります。
クラスベースビューの作成
続いて、このページの本題でもあるクラスベースビューの作成を行っていきます。今回は、ここまでの説明の通り CreateView を継承するクラスを定義し、そのクラスをクラス変数の定義とメソッドのオーバーライドによってカスタマイズしていきます。
今回は、下記のように views.py を変更することでクラスベースビューを作成したいと思います。
from django.views.generic import DetailView, CreateView
from .models import Comment
from .forms import CreateCommentForm
from django.urls import reverse
class CommentCreate(CreateView):
form_class = CreateCommentForm
initial = {
'text': 'hello'
}
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 においては2つのクラスを定義しており、一方は DetailView を継承するクラスとして CommentDetail を定義しています。このクラスは、CommentCreate の post メソッドが実行された際のリダイレクト先として利用するために定義しています。
DetailView に関しては下記ページで詳細を解説していますので、詳しく知りたい方は下記ページを参照してください。
また、もう1つのクラスが、このページで解説している CreateView を継承するクラスとなります。このクラスでは form_class に CreateCommentForm を指定しているため、フォームを扱う際には CreateCommentForm が利用されることになります。
また、CreateCommentForm の meta 属性の model に Comment を指定しているため、このフォームから送信されてきたデータをレコードとして保存する際には、Comment に対応するテーブルに保存が行われることになります。こんな感じで、CreateView を継承するクラスでは様々なクラスが連携して動作することになる点も CreateView を理解するポイントの1つになると思います。そして、様々なクラスが連携して動作することになるため、CreateView のカスタマイズだけでなく、フォームクラスやモデルクラスの変更によってビューの動作を変更することも可能となります。
例えば、上記の CommentCreate では get_success_url をオーバーライドしています。このオーバーライドによる効果は get_success_url で既に解説したつもりなので、ここでの詳細な説明は省略しますが、下記のように、Comment クラスに get_absolute_url を定義しておくことでも同様のことを行うことが可能です。
def get_absolute_url(self):
return reverse('comment', kwargs={'comment_id': self.id})
CreateView の get_success_url では、クラス変数 success_url が定義されていない場合、事前にデータベースに保存されたインスタンスによる get_absolute_url メソッドの実行結果が返却されるようになっています。今回の例であれば、CommentCreate によってデータベースに保存されるインスタンスは Comment クラスのものとなるため、Comment の get_absolute_url の実行結果が get_success_url の返却値、すなわちリダイレクト先の URL として扱われることになります。そのため、get_absolute_url で動的に URL を生成して返却するようにしておけば、get_success_url のオーバーライドを行わなくてもリダイレクト先の URL を動的に変更することが可能となります。
スポンサーリンク
ビューと URL とのマッピング
少し横道にそれましたが、次は views.py で定義したビューと URL とのマッピングを行なっていきます。
まず、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 を新規作成し、中身を下記のように変更してください。
from django.urls import path
from . import views
urlpatterns = [
path('comment/<int:comment_id>/', views.CommentDetail.as_view(), name='comment'),
path('create/', views.CommentCreate.as_view(), name='create'),
]
これらの urls.py により、ルートパス指定で /forum/create/ へのリクエストがあった際に CommentCreate の get メソッドが実行されてフォームが表示されるようになります。そして、フォームからデータが送信されてきた際には post メソッドが実行され、さらにはデータベースに保存されたインスタンスのプライマリーキーを comment_id として 'comment' の名前が付けられた URL にリダイレクトされます( つまり /forum/comment/プライマリーキー/ へリダイレクトされる)。それにより、次は CommentDetail の get メソッドが実行されることになり、その保存されたインスタンスの詳細情報が表示されることになります。
テンプレートの作成
次はテンプレートファイルを作成します。ソースコードの変更としては、これが最後となります。
CommentCreate が利用するテンプレートファイル
まず、CommentCreate ではクラス変数 template_name を定義し、template_name には 'forum/commentcreate.html' を指定しているため、アプリ内の templates フォルダから見た相対パスが 'forum/commentcreate.html' となる位置に存在するテンプレートファイルが利用されることになります。
このパスにテンプレートファイルを用意しておく必要があるため、forum フォルダの中にまず templates フォルダを作成し、さらに templates の中に forum フォルダを作成してください。
さらに、最後に作成した forum フォルダの中に 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>
このテンプレートファイルでは変数として form を参照しています。で、CreateView が生成するコンテキストで説明したように、CreateView で生成されるコンテキストには 'form' キーとして form_class で指定されたフォームクラスのインスタンス or model + fields から生成されるフォームクラスのインスタンスがセットされることになるため、このテンプレートファイルでは form を参照することでフォームクラスのインスタンスが扱えることになります。そして、{{ form.as_table }} と記述しておけば、そのフォームクラスに定義されているフィールドがテーブル形式で HTML に埋め込まれることになります。そして、それがページとして表示されることで、それらの入力フィールドを含むフォームが表示されることになります。
CommentDetail が利用するテンプレートファイル
また、CommentDetail で利用されるテンプレートファイルに関しては下記ページで紹介していますので、これに関しては下記ページをご参照いただければと思います。
結論としては、先ほど最後に作成した forum フォルダの下に 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 をウェブブラウザで表示すれば下図のような text と slug の入力フィールドを持つフォームが表示されるはずです。

ここで表示されるフォームは CreateCommentForm で定義されるクラスのインスタンスであり、CreateCommentForm で Meta 属性の fields に ['text', 'slug'] を、model に Comment を指定しているため、Comment の text と slug フィールドを入力するためのフォームが表示されることになります。
また、text フィールドに hello とあらかじめ入力されているのは CommentCreate クラスのクラス変数として initial ={'text': 'hello'} を指定しているからになります。
表示されたフォームで適当な半角英数字の文字列を text と slug に入力して 送信 ボタンを押せば、これらのフィールドに入力されたデータが対応するフィールドにセットされ、さらに id(プライマリーキー) と date(新規作成された日時) が自動的にセットされた Comment のインスタンスがデータベースに新規登録されることになります。ただし、slug に関してはデータベースに保存されている他の Comment のインスタンスと重複していると妥当性の検証結果が NG になるようになっているので注意してください。
送信 ボタンを押してインスタンスがデータベースに新規登録されれば、リダイレクトが行われ、そのインスタンスの詳細ページに自動的に遷移するようになっているはずです。

このリダイレクト先の URL は CommentCreate クラスの get_success_url によって決定され、そのリダイレクト先の URL は下記となります。
http://localhost:8000/forum/comment/<int:comment_id>/
この <int:comment_id> には、フォームの送信によって新規保存されたインスタンスのプライマリーキーが自動的に設定されてリダイレクトされるようになっています。
こんな感じで、CreateView を継承するクラスを定義してクラス変数やメソッドを適切に定義してやれば、簡単にインスタンス(レコード)の新規登録を行うビューを実現することができます。モデルクラスの定義やモデルフォームクラスの定義、さらにはクラス変数やメソッドの定義を変えてみて、その時に動作がどう変わるのかを確認していけば、もっと CreateView への理解が深まると思いますので、是非これらにも挑戦してみてください!
スポンサーリンク
まとめ
このページでは、CreateView および CreateView を継承したクラスベースビューの作り方について解説しました!
CreateView はインスタンス(レコード)をデータベースに新規登録するための View のサブクラス であり、このクラスを継承することでユーザー登録やコメントの新規投稿等を行うページを簡単に実現できます。
CreateView のポイントの1つはフォームを扱うという点であり、そのためにフォームクラスの定義やフォームクラスに関するクラス変数の定義等が必要になります。
また、POST メソッドのリクエストを扱うことができるという点もポイントとなります。関数ベースビューの場合はリクエストのメソッドに応じて動作を切り替えるような処理を実装する必要があって若干ややこしいですが、クラスベースビューの場合はこのあたりの処理の実装が不要となり、クラスベースビューに置き換えることで実装が簡潔になります。なので、ListView や DetailView 等に比べてクラスベースビューに置き換えるメリットも大きいと思います。
こういったインスタンスのデータベースへの新規登録に関してもウェブアプリで実装する機会が多い機能となると思いますので、CreateView も使いこなせるようになっておきましょう!
このサイトでは他の View のサブクラス についても説明していますので、他のページも是非読んでみてください!

