このページでは、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
を継承することで簡単に作成することが可能です。
また、View のサブクラス
には、下記ページでも紹介している ListView
や DetailView
が存在しています。


これらのクラスは表示に特化したものであり、基本的には HTTP のリクエストにおける GET
にのみ対応しています。そして、これらのクラスではリクエストを受け取った際に get
メソッドが実行されるようになっています。
それに対し、CreateView
は GET
のみだけではなく POST
にも対応しています。そのため、ページの表示だけでなく、ユーザーから送信されてきたデータに基づいたレコードを生成し、それをデータベースに新規登録するようなことが可能となっています。
もう少し詳細に説明すると、CreateView
はメソッドが GET
のリクエストを受け取った際には get
メソッドが実行され、メソッドが POST
のリクエストを受け取った際には post
メソッドが実行されるようになっています。この辺りが、CreateView
と ListView
/ DetailView
との一番大きな違いになると思います。
で、この POST
にも対応している分、CreateView
を継承するクラスを扱うのは ListView
や DetailView
よりも難易度が若干高くなります。まぁでも、この辺りは関数ベースでビューを扱う場合も一緒だと思います。クラスベースでも関数ベースでも結局 POST
に対応する分の労力が必要になります。
ですが、POST
への対応に関して言えば、関数ベースビューよりもクラスベースビューの方が確実に楽に実現できると思います。関数ベースビューの場合は、関数の中でメソッドが GET
であるか POST
であるかを判断し、その判断結果に基づいて処理を切り変えるような実装を開発者自身が行う必要があります。
この辺りは、下記のフォームの解説ページで説明していますので、詳しく知りたい方は下記ページをご参照いただければと思います。

それに対し、クラスベースビューの場合、メソッドが GET
であるか POST
であるかの判断を行い、それに応じて動作を切り替えるような処理が Django フレームワークの中で既に実装されています。そして、それがクラスとして定義されている例の1つが、今回扱う CreateView
となります。したがって、開発者は、関数ベースビューでは必要だったメソッドに応じた処理の切り替えを実装する必要はありません。
つまり、次の CreateView でのクラスベースビューの作り方 で説明する手順で CreateView
を継承するクラスを定義しておけば、あとはリクエストを受け取った際にリクエストに応じた処理が自動的に実行されるようになっています。そのため、CreateView
を継承してクラスベースビューを作成することで処理の実装量を減らすことができますし、メソッドに応じた分岐処理等の実装も不要となるためバグも発生しにくくなります。
CreateView
でのクラスベースビューの作り方
では、次はその CreateView
でクラスベースビューを作成する手順について説明していきます。
CreateView
でのクラスベースビューの作り方は、大まかに言えば ListView
や DetailView
等の他の View のサブクラス
の時と同様です。
要は、views.py
に CreateView
を継承するクラスを定義し、views.py
に定義したクラスにクラス変数やメソッドを定義することで CreateView
で定義されているクラス変数の上書き・メソッドのオーバーライドを行なっていきます。これにより、CreateView
の特徴を活かしながら自身のウェブアプリに応じたビューにカスタマイズしていくことが可能となります。
もう少し具体的に言えば、前述の通り、CreateView
ではリクエストに応じて get
メソッドや post
メソッドが実行されるようになっており、CreateView
のクラス変数や他のメソッドは、これらの get
メソッドおよび post
メソッドから利用されるようになっています。したがって、CreateView
を継承するクラス側でクラス変数やメソッドを上書き・オーバーライドしてやれば、この get
メソッドと post
メソッドの動作を変化させることができます。
スポンサーリンク
利用するフォームを設定する
この CreateView
でクラスベースビューを作成する場合にポイントになるのがクラス変数によるフォームクラスの設定になります。
まず、インスタンスの新規登録を実現するためには、get
メソッドが実行された際に新規登録するインスタンス(レコード)の情報の入力・送信を受け付けるためのフォームを表示する必要があります。そして、このフォームはフォームクラスのインスタンスを HTML に要素として埋め込むことで表示されるようになっており、そのインスタンスのクラスを CreateView
を継承するクラス側で設定しておく必要があります。
また、post
メソッド実行時にもフォームクラスのインスタンスが必要となります。そのため、そのインスタンスの基になるフォームクラスを CreateView
を継承するクラス側で設定しておく必要があります。
具体的にいうと、post
メソッド実行時はフォームから送信されてきたデータを受け取り、そのデータからフォームクラスのインスタンスが生成されます。そして、このインスタンスに is_valid
メソッドを実行させることで、送信されてきたデータの妥当性の検証が行われます。さらに、妥当性の検証結果が OK の場合は、そのインスタンスに save
メソッドを実行させることで、送信されてきたデータがレコードとしてデータベースへ新規登録されることになります。
ここでポイントになるのがフォームクラスのインスタンスの save
メソッドが実行されるという点になります。通常のフォームクラスには save
メソッドが存在しないため、CreateView
を継承するクラスで利用するのは単なるフォームクラスではなくモデルフォームクラスである必要があることになります。下記ページでも解説しているとおり、モデルフォームクラスは model
に指定したモデルクラスに基づいて生成されるクラスであり、このクラスのインスタンスに save
メソッドを実行させれば、その model
に指定したモデルクラスに対応するテーブルにインスタンスが保存されることになります。

ここで覚えておいていただきたいのは、データベースへの新規登録を行うためには、新規登録先のテーブルを指定する必要があり、それを決めるのがモデルフォームクラスになるという点になります。
post
メソッド実行時の動作の説明に戻ると、post
メソッドから妥当性の検証が行われて検証結果が NG の場合は、フォームクラスのインスタンスを再度 HTML に埋め込んだものをレスポンスとしてクライアントに返却することで、クライアント側で再度フォームの表示及び入力の再受付が行われるようになっています。
このような動作はフォームを扱う上での典型的な処理の流れとなっており、先ほども紹介した下記ページのフォームの解説ページでも詳しく説明していますので、復習したい方は是非下記ページを読んでみてください。

このように、CreateView
および CreateView
のサブクラスでは多くの場面でフォームクラスが利用されることになり、CreateView
のサブクラスを定義する際にはフォームクラスの設定が非常に重要となります。
そして、CreateView
のサブクラスで利用するフォームクラスは、下記のクラス変数を定義することで設定することができます。
- クラス変数
form_class
を定義する - クラス変数
model
とfields
を定義する
前者に関しては分かりやすくて、クラス変数 form_class
を定義して CreateView
のサブクラスで利用するフォームクラスを直接指定する実現方法になります。クラス変数 form_class
を定義することで、form_class
に指定したフォームクラスが CreateView
のサブクラスから利用されるようになり、そのクラスのインスタンスがフォーム要素としてページに表示されたりデータベースへの保存を行なったりするようになります。
前述の通り、form_class
にはモデルフォームクラスを指定する必要があります。モデルフォームクラスに関しては下記ページで解説していますので、モデルフォームクラスをご存知ない方は下記ページを参照してください。要は、モデルクラスに基づいて自動的に生成されるフォームクラスがモデルフォームクラスとなります。

後者に関しては、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
のオーバーライドにより実現することができます。
ここで説明したような、利用するフォームクラスの設定方法、リダイレクト先の設定方法、妥当性の検証結果が OK の場合に実行する処理の変更方法は 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
スポンサーリンク
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
を定義した場合、
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'
テンプレートファイルは forum/templates/forum/create.html
に用意しておく必要があります。また、これに関しては後述の CreateView が生成するコンテキスト で説明しますが、CreateView
が生成するコンテキストには form
キーに form_class
で指定したフォームクラスのインスタンス or model
+ fields
から生成されるクラスのインスタンスがセットされることになるため、用意するテンプレートファイルでは form
変数をフォームとして表示するようにしておく必要があります。
スポンサーリンク
template_name_suffix
先ほど template_name
を定義しなかった場合、テンプレートファイルのパスとして アプリ名/モデルクラス名_form.html
がデフォルトで設定されると言いましたが、この _form
部分はクラス変数 template_name_suffix
を定義して変更することも可能です。また、モデルクラス名
部分は model
に指定したモデルクラスのクラス名を小文字にしたものになります。
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
となります。
template_name
を定義しない場合、利用するテンプレートファイルのパスが template_name_suffix
だけでなく model
に指定したモデルクラスのクラス名を参照して決定されるという点もポイントとなります。つまり、テンプレートファイルのパスを決定するためには model
を指定してやる必要があります。template_name
を定義せず、さらに model
も定義しなかった場合、下記のような例外が発生することになるので注意してください。
TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
この例外は、クラス変数 model
を定義する(queryset
でもオーケー)、もしくはクラス変数 template_name
を定義することで解消することができます。
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_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 である場合に実行されるメソッドで、このメソッド内部ではフォームから送信されてきたデータをレコードとしてデータベースに保存し、さらに特定の URL にリダイレクトするためのレスポンスを返却する処理が行われるようになっています。
ちなみに、Django においてレコードとはインスタンスのことであり、form_valid
の中では、form_class
で指定されるモデルフォームのベースとなるモデルクラスのインスタンス or model
で指定されるモデルクラスのインスタンスがデータベースに保存されることになります。また、保存先のテーブルは上記のモデルクラスに対応するテーブルとなります(Django においては、モデルクラスがデータベースにおけるテーブルを表しています)。
form_valid
ではこれらの処理が自動的に行われるようになっているのですが、逆に言えば、これら以外の処理は行われないため、妥当性の検証結果が OK の時の処理を変更したい場合は、form_valid
のオーバーライドを行う必要があります。
ここでは詳細な説明は省略しますが、レコードの保存はフォームクラスの save
メソッドで実行されるため、そういった CreateView
から継承されるメソッド以外のメソッドで他の処理を追加することも可能です
例えば、ログイン機能を備えたアプリを開発している際に、ユーザーの新規登録が行われた際にログイン処理も一緒に実行したいような場合があります。ユーザーの新規登録はデータベースへのレコードの保存によって実現されるため、form_valid
によってユーザーの新規登録を行うことは可能です。ですが、form_valid
ではその後にリダイレクトのレスポンスを返却して処理を終了するようになっているため、CreateView
の form_valid
ではユーザーの新規登録後のログイン処理を実現することができません…。
ですが、CreateView
のサブクラス側で form_valid
をオーバーライドしてやれば、post
から form_valid
が呼び出しされる際には CreateView
のサブクラス側の form_valid
が実行されるようになり、そこで様々な処理を追加で行うようなことが可能となります。
例えば下記は、【Django入門14】クラスベースビューの基本 の 掲示板アプリのビューをクラスベースに変更する で紹介した form_valid
のオーバーライドの例になります。
下記のように 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
は基本的にリダイレクトのレスポンスを返却する必要がある点に注意してください。CreateView
の form_valid
の返却値もリダイレクトのレスポンスとなりますので、その返却値をオーバーライドした側の form_valid
でも返却するようにしてやればリダイレクトのレスポンスの返却を実現することができることになります。上記においては return response
の部分がそれにあたります。
今回はログイン処理の例を示しましたが、他にも様々な処理を form_valid
に追加することが可能です。また、フォームから送信されてきたデータの妥当性の検証結果が 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_success_url
の返却値が返却されることになります。
なので、基本的にはクラス変数 success_url
を定義してリダイレクト先の URL を指定するので良いです。ですが、クラス変数の場合、アプリ起動時に静的にクラス変数への指定値が決まることになりますので、動的にリダイレクト先の URL を変化させたいような場合はクラス変数の定義ではなくメソッドで実現する必要があります。その具体的な方法の1つが get_success_url
のオーバーライドとなります。
前述の通り、クラス変数 success_url
が定義されていない場合、モデルクラス側の get_absolute_url
メソッドが呼び出されることになります
したがって、モデルクラス側の get_absolute_url
を定義して動的にリダイレクト先の URL を生成して返却するようにすることも可能です
これに関しては、後述の CreateView の利用例 で補足します
例えば下記は、【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
では reverse
関数の kwargs
の 'user_id'
のキーの値として self.object.pk
を指定しているため、リダイレクト先の URL として、データベースに新規登録した User
クラスのインスタンスに割り当てられたプライマリーキーに対応した URL が返却されることになります。このプライマリーキーはインスタンスがデータベースに新規登録されるタイミングで毎回異なるものがインスタンスに割りられるフィールドです。そのため、インスタンスの新規登録のたびに、そのインスタンスのプライマリーキーに応じて毎回異なる URL が返却されることになり、動的にリダイレクト先の URL が変化することになります。
CreateView
が生成するコンテキスト
続いて CreateView
が生成するコンテキストについて説明しておきます。
CreateView
が生成するコンテキストには下記の要素が含まれます。見てわかる通り、基本的に CreateView
が生成するコンテキストは 'form'
キーのみを持つことになります。
'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
実行結果が get_success_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 にリダイレクトされます。それにより、次は 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 のサブクラス
についても説明していますので、他のページも是非読んでみてください!




