概要
フォームのバリデーションを行う際にセッション情報を使いたかったのですが、Django のフォームクラスではリクエストオブジェクトを参照することができません。
セッション情報をコンテキストとしてフォームの hidden 属性で渡したりできますが、、いかんせん格好悪い。
ということで、フォームクラスのメソッドをオーバーライドしてリクエストオブジェクトを渡す方法を紹介します。
検証環境は Python 3.8, Django 3.1.1 です。
forms.py
フォームクラスはデフォルトのキーワード引数として initial や data といったパラメータしか受け取れません。
なので、__init__
メソッドをオーバーライドして、フォームのインスタンス生成時に request パラメータを引数として受け取るようにします。
https://github.com/django/django/blob/master/django/forms/forms.py#L64
class MyForm(forms.form):
def __init__(self, request, *args, **kwargs):
self.request = request
super(MyForm, self).__init__(*args, **kwargs)
views.py
フォームクラスで request をインスタンス引数として受け取るようにしたので、ビュー側でフォームインスタンスを生成する際にリクエストオブジェクトを渡すようにします。
関数ビュー
シンプルにリクエストオブジェクトを引数で渡せばOK。
def my_form_view(request):
form = MyForm(request=request, data=request.POST)
クラスビュー
FormView の継承元である FormMixin には、フォームインスタンス生成時にキーワード引数として渡す値を指定するための get_form_kwargs()
というメソッドがあります。initial や data といったパラメータを渡します。
https://github.com/django/django/blob/3.0/django/views/generic/edit.py#L35
このメソッドをオーバーライドして、ビュー側から request データを kwargs としてフォームインスタンスに渡すようにします。
class MyFormView(FormView):
form_class = MyForm
def get_form_kwargs(self):
kwargs = super(MyFormView, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
これでフォームクラスでもリクエストオブジェクトを参照できるようになりました。
あとは、clean メソッドなどで self.request.session.get('foo')
のようにしてセッション情報を取得できます!