(最終更新月:2021年10月)
「Selectタグ 選択要素を動的な値にしたい!」
「任意の値をフォームへ渡し、選択肢を作りたい!」
と考えている方も多いのではないでしょうか?
当記事では、Django初学者の方向けに
- Django Form内のChoiceField choicesを動的に操作する
方法をお伝えします
まずは決まった値を選択肢とする方法をカンタンにおさらいし、本題へと進みます
【バージョン情報】
- OS: Ubuntu 20.10
- Python: 3.8.10
- Django: 3.1.4
- PostgreSQL: 12.7
- React: 17.0.1
決まった値を選択肢とする方法
選択肢とする値が決まっている場合、
CHOICES_TUPLE = (("データベースに保存する名前", "HTML内で表示する文字列"), (.., ..), ....)
とし、CHOICES_TUPLEという選択肢を作成します
ChoiceFieldの引数「choices」にCHOICES_TUPLEを入れることで、
some_field = forms.ChoiceField(choices=CHOICES_TUPLE)
ChoideFieldの選択肢がCHOICE_TUPLEの値になります
好きな値を選択肢にする
大まかな流れは、
- views.py内で好きな選択肢を作成する
- views.py内のget_form_kwargs関数でforms.pyへ選択肢を渡す
- forms.py内で選択肢を受け取り、ChoiceFieldへ割り当てる
となります
【views.py】get_form_kwargs()内
クラスベースビューに備わっているget_form_kwargsメソッドは、フォームへ値を渡す役割を担っています
def get_form_kwargs(self, *args, **kwargs):
kwgs = super().get_form_kwargs(*args, **kwargs)
category_choice = (("choice1", "1"), ("choice2", "2"), ("choice3", "3"))
kwgs["categories"] = category_choice
return kwgs
category_choiceという選択肢をお好きに作成してください
今回は決まった値にしていますが、仮にこちらをデータベースから取り出したQuerySetなどにすると保存されている情報により選択肢が変わる「動的な選択肢」となります
kwgs["categories"] = category_choice
とし、forms.pyへ渡します
【forms.py】
class LeadForm(forms.ModelForm):
category = forms.ChoiceField()
class Meta:
model = Lead
fields = "__all__"
def __init__(self, categories=None, *args, **kwargs):
self.base_fields["category"].choices = categories
super().__init__(*args, **kwargs)
views.pyより渡された値は、__init__メソッド内で処理します
__init__メソッド内で気をつけることは、
- 引数でviews.pyから渡された「キー」を受け取ること
- self.base_fieldsで、ChoiceFieldを指定しているフィールド名を指定すること
- フィールドのchoices属性にviews.pyから受け取った「categories」をパスすること
の3点です
まとめ
以上で、好きな選択肢をテンプレートに反映されることが可能です
前に記述の通りデータベースから保存したデータを選択肢としたり、ランダムな数値などを選択肢としたり、とすることで動的な選択肢を作成することもカンタンにできます
また、views.pyから値を渡さずともforms.py内で処理をすることもできるので自分にとってカンタンな方法で試してみてください!
具体的に動的な選択肢を作成する方法として、ArrayFieldで保存された値を選択肢とする方法をこちらの記事で解説しています↓