こんにちは!内藤です!
だいぶ時間が経ってしまいましたが、前回の記事の続きです!
Index
- 基本的なクラスのシーケンス(前回の記事)
- View
- RedirectView
- TemplateView
- DetailView
- ListView
- CRUDクラスのシーケンス(この記事)
- FormView
- CreateView
- UpdateView
- DeleteView
前提条件
- 対象のDjangoバージョンは、手元にあった 3.2.13 です
- 現場で使える Django の教科書《基礎編》の内容程度が頭に入っている人向け
- 対象とするクラスは、下記
- View
- RedirectView
- TemplateView
- DetailView
- ListView
- FormView
- CreateView
- UpdateView
- DeleteView
django.views.generic.edit.FormView
入力を検証するためのFormを使用するViewです。
ソースコードはこちら
GETメソッド、POSTメソッドでFormの検証が通った場合、POSTメソッドでFormの検証が通らなかった場合にわけてコールグラフを起こしてみました。
GET時のコールグラフ
関数名 | 処理内容 |
---|---|
FormMixIn.get_context_data | テンプレートエンジンに渡すための context を生成します。 context には、FormView.get_form で生成した Form オブジェクトが 'form' というキー名で context に追加されます |
FormMixIn.get_form | 検証用の Form オブジェクトを生成します。 FormView.get_form_class メソッドで生成する Form クラスを取得し、 FormView.get_form_kwargs メソッドで Form クラスのインスタンスを生成します |
FormMixIn.get_form_class | 検証も使用する Form オブジェクトのクラス名を取得します。 デフォルトでは、クラスフィールド form_class を使用します |
FormView.get_form_kwargs | 検証に使用する Form オブジェクトのコンストラクタに渡す引数を dict として取得します。 下記のキーで、それぞれの値を設定します。 ・キー'initial' ... Form オブジェクトに渡す初期値 |
キー'prefix' ... Form オブジェクトに渡すプレフィックス ・キー'data' ... POSTまたはPUTメソッドの時、渡されたデータ ・キー'files' ... POSTまたはPUTメソッドの時、アップロードされたファイルデータ |
|
FormView.get_initial | 検証に使用する Form オブジェクトの初期値を返します。 デフォルトでは、クラスフィールド initial を使用します |
FormView.get_prefix | 検証に使用する Form オブジェクトのプレフィックスを返します。 デフォルトでは、クラスフィールド prefix を使用します |
ContextMixin.get_context_data | django.views.generic.base.TemplateViewに記述した内容です。 |
TemplateResponseMixin.get_template_names | レンダリングするテンプレート名をリストで返します。 クラス変数 template_name の内容を返します。 |
TemplateResponseMixin.render_to_response | テンプレートをレンダリングしてレスポンスを返します。 |
入力検証に使用する Form オブジェクトを生成して、指定したテンプレートをレンダリングして返します。
POST, 検証OK時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが True を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
FormView.form_valid | 検証用の Form オブジェクトによる検証がOKだった時に呼ばれます。 デフォルトでは、成功時のURLにリダイレクトします。 |
FormView.get_success_url | 検証OKだった時のリダイレクト先を返します。 デフォルトでは、クラスフィールド success_url を返します。 |
POST, 検証NG時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが False を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
また、FormMixIn.get_context_data 移行の流れも、GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
FormView.form_invalid | 検証用の Form オブジェクトによる検証がNGだった時に呼ばれます。 get_context_data メソッドを呼び出して context を生成し、 render_to_response メソッドに渡します |
PUTメソッドはPOSTメソッドとまったく同様なので、省略します。
オーバーライドの例
Form オブジェクトの検証に、画面上に表示しないデータ(例えばログインユーザ情報や settings の内容)を渡したい場合、get_form_kwargs メソッドをオーバーライドします。
from django.views.generic.edit import FormView
from myform import MyForm
class MyFormView(FormView):
form_class = MyForm # コンストラクタをオーバーライドしたFormクラス
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
from django.forms.models import ModelForm
class MyForm(ModelForm):
class Meta(ModelForm):
model = '対象のモデルクラス'
def __init__(self, *args, **kwargs):
# View側のget_form_kwargsで追加したパラメータを取得する
# ModelFormを継承する場合、モデルに定義されていないフィールド名をパラメータに受け取ると例外発生するので
# super().__init__呼び出し前にpopして除去しておく
self.user = kwargs.pop('user', None)
super()__init__(*args, **kwargs)
django.views.generic.edit.CreateView
モデルインスタンスを新規に作成するためのViewです。
ソースコードはこちら
GET時のコールグラフ
だいぶサイズが大きくなってきました。
関数名 | 処理内容 |
---|---|
BaseCreateView.get | 自身の object フィールドを None に初期化します。 |
FormMixIn.get_context_data | FormViewに記述した内容です。 |
FormMixIn.get_form | FormViewに記述した内容です。 |
FormMixIn.get_form_class | FormViewに記述した内容です。 |
ModelFormMixIn.get_form_class | クラスフィールド form_class を指定しなかった際に、関連付けられているモデル情報から Form オブジェクトのクラス名を生成しようとします。 |
FormView.get_form_kwargs | FormViewに記述した内容です。 |
ModelFormView.get_form_kwargs | FormView.get_form_kwargs に加えて、下記のキーと値を設定します。 ・キー'instance' ... self.object を設定します。 |
FormView.get_initial | FormViewに記述した内容です。 |
FormView.get_prefix | FormViewに記述した内容です。 |
SingleObjectMixin.get_context_data | DetailViewに記述した内容です。 |
ContextMixin.get_context_data | TemplateViewに記述した内容です。 |
TemplateResponseMixin.get_template_names | レンダリングするテンプレート名をリストで返します。 クラス変数 template_name の内容を返します。 |
TemplateResponseMixin.render_to_response | テンプレートをレンダリングしてレスポンスを返します。 |
入力検証に使用する Form オブジェクトを生成して、指定したテンプレートをレンダリングして返します。
POST, 検証OK時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが True を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
BaseCreateView.post | 自身の object フィールドを None に初期化します。 |
ModelFormView.form_valid | 検証用の Form オブジェクトによる検証がOKだった時に呼ばれます。 Form オブジェクトの save メソッドを呼び出し、戻り値を self.object に保持します。 |
FormView.form_valid | FormViewに記述した内容です。 |
FormView.get_success_url | FormViewに記述した内容です。 |
POST, 検証NG時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが False を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
また、FormMixIn.get_context_data 移行の流れも、GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
FormView.form_invalid | 検証用の Form オブジェクトによる検証がNGだった時に呼ばれます。 get_context_data メソッドを呼び出して context を生成し、 render_to_response メソッドに渡します |
オーバーライドの例
FormViewに記載した内容は、そのまま CreateView でも使えます。
django.views.generic.edit.UpdaeView
既存のモデルインスタンスを更新するためのViewです。
ソースコードはこちら
GET時のコールグラフ
ほとんど CreateView の GET時の処理と変わりません。
異なる部分のみ、内容を取りまとめます。
関数名 | 処理内容 |
---|---|
BaseUpdateView.get | 自身の object フィールドを SingleObjectMixin.get_object の戻り値で初期化します。 ここで取得したオブジェクトが更新対象となります。 |
SingleObjectMixin.get_object | DetailViewに記述した内容です。 |
SingleObjectMixin.get_queryset | DetailViewに記述した内容です。 |
ModelFormView.get_form_kwargs | CreateViewと処理は同じですが、UpdateView は BaseUpdateView.get メソッドで self.object に更新対象のモデルオブジェクトを保持しています。 そのため、Form オブジェクトのコンストラクタにキー'instance'として、更新対象のモデルオブジェクトが渡ります。 |
POST, 検証OK時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが True を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
BaseUpdateView.post | 自身の object フィールドを SingleObjectMixin.get_object の戻り値で初期化します。 ここで取得したオブジェクトが更新対象となります。 |
ModelFormView.form_valid | 検証用の Form オブジェクトによる検証がOKだった時に呼ばれます。 Form オブジェクトの save メソッドを呼び出し、戻り値を self.object に保持します。 |
FormView.form_valid | FormViewに記述した内容です。 |
FormView.get_success_url | FormViewに記述した内容です。 |
POST, 検証NG時のコールグラフ
POSTメソッドで、検証に使用した Form オブジェクトの is_valid メソッドが False を返す場合です。
FormMixIn.get_form ~ FormView.get_prefix までの流れは GET メソッドの時と同じです。
また、FormMixIn.get_context_data 移行の流れも、GET メソッドの時と同じです。
関数名 | 処理内容 |
---|---|
BaseUpdateView.post | 自身の object フィールドを SingleObjectMixin.get_object の戻り値で初期化します。 ここで取得したオブジェクトが更新対象となります。 |
FormView.form_invalid | 検証用の Form オブジェクトによる検証がNGだった時に呼ばれます。 get_context_data メソッドを呼び出して context を生成し、 render_to_response メソッドに渡します |
オーバーライドの例
FormViewに記載した内容は、そのまま UpdateView でも使えます。
django.views.generic.edit.DeleteView
既存のモデルインスタンスを削除するためのViewです。
ソースコードはこちら
対象のモデルインスタンスを取得処理を流用するために、BaseDetailView を継承しています。
継承関係は複雑ですが、使用している処理はごくわずかです。
POSTメソッドのみサポートしています。
コールグラフ
関数名 | 処理内容 |
---|---|
DeletionMixIn.post | DeletionMixIn.delete メソッドを呼び出します。 |
DeletionMixIn.delete | SingleObjectMixin.get_object で対象のモデルオブジェクトを取得し、delete メソッドを呼び出して削除します。 その後、get_success_url メソッドで遷移先URLを取得してリダイレクトします。 |
DeletionMixIn.get_success_url | 削除後のリダイレクト先URLを返します。 クラスフィールド success_url が指定されている場合、その値に を実行して返します。クラスフィールド success_url に書式指定文字列を埋めておけば、削除したモデルオブジェクトに依存したURLが生成できます。 |
オーバーライドの例
実際にオブジェクトを削除するのは delete メソッドです。
ここをオーバーライドすれば、論理削除が実装できます。
from django.http import HttpResponseRedirect
from django.views.generic.edit import DeleteView
class MyDeleteView(DeleteView):
model = '対象のモデルクラス名'
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
# ここで論理削除っぽい動きをする。例えば下記
# self.object.is_deleted = True # 削除フラグを立てる
return HttpResponseRedirect(success_url)