Django の form で 自身のフィールドを参照する方法には fields と base_fields の2種類があります。
その使い分けについて説明します。
実体験と調べた内容からの理解となります。厳密なところでは認識誤りがあるかもしれません。
fields と base_fields
以下の form を例にして説明します。
# forms.py
from django.forms import Form, ChoiceField
class SampleForm(Form):
select = ChoiceField()
fields
fields は init 後に使うことができるようになります。インスタンス内にのみ影響を及ぼします。
SampleForm の場合
def __init__(self, *args, **kwargs):
# ここでは fields は使えない
super().__init__(*args, **kwargs)
# ここからは使用できる
self.fields["select"].choices = [(1, "一"), (2, "二")]
base_fields
base_fields はいつでも参照可能です。変更はシステム全体に影響を及ぼします。
def __init__(self, *args, **kwargs):
# init 前でも使える
self.base_fields["select"].choices = [(1, "一"), (2, "二")]
super().__init__(*args, **kwargs)
# init 後でも使える
self.base_fields["select"].choices = [(0, "零"), (1, "壱"), (2, "弐")]
使い分け
全体に変更を適用していい場合は base_fields, インスタンスのみであれば fields という使い分けでいいと思います。 base_fields は全てに共通な定義を設定するみたいなイメージです。
SampleForm の select のような ChoiceField では選択肢 (choices) を付与できますが、データによっては可変にしたいということもあるかと思います。
その場合には init などで設定することになりますが、base_fields ではなく fields を使用します。
base_fields に設定した場合、表示時には与えた選択肢で表示できているが、post するまでの間に他のユーザーなどが同じ form を使って別の選択肢を生成した場合などで選択肢が存在しないエラーが発生する可能性が出てきます。
※そのデータに対して選択肢を毎回必ず設定できるのであれば問題ないかもしれません。
以上、簡単ですが fields の使い分けについてでした。