概要
DjangoでChoiceFieldを触っていて、時間のかかった箇所を忘備録として残しておきます。
サンプルコードはこちら
目次
ChoiceFieldについて
- 複数の選択肢から一つを選ぶフィールド
- デフォルトの描画は
django.forms.widgets.Select
- テンプレートに描画すると
<select name="フィールド名"><option value="choice.key">choice.value</option>...</select>
となる
- テンプレートに描画すると
- 参考:Form Fields:ChoiceField
サンプル
forms.py
from django import forms
class SampleChoiceForm(forms.Form):
choice1 = forms.fields.ChoiceField(
choices = (
('ja', '日本'),
('us', 'アメリカ'),
('uk', 'イギリス'),
('ch', '中国'),
('kr', '韓国')
),
required=True,
widget=forms.widgets.Select
)
views.py
from django.shortcuts import render
from django.views import View
from . import forms
class SampleChoiceView(View):
def get(self, request):
form = forms.SampleChoiceForm()
context = {
'form': form
}
return render(request, 'choice_sample.html', context)
sample_choice_view = SampleChoiceView.as_view()
choice_sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>ChoiceFieldサンプル</title>
</head>
<body>
<form method="POST" aciton="">
{% for field in form %}
{{ field }}
{% endfor %}
{% csrf_token %}
</form>
</body>
</html>
出力結果
<!doctype html>
<html lang="ja">
<head>
<title>ChoiceFieldサンプル</title>
</head>
<body>
<form method="POST" action="">
<select id="id_choice1" name="choice1">
<option value="ja">日本</option>
<option value="us">アメリカ</option>
<option value="uk">イギリス</option>
<option value="ch">中国</option>
<option value="kr">韓国</option>
</select>
<input type="hidden" name="csrfmiddlewaretoken" value="xxxxxxxx" />
</form>
</body>
</html>
表示
時間のかかった箇所
- 選択肢を後から追加する方法
選択肢を後から追加する方法
公式チュートリアルやDjango Girls チュートリアルでは、選択肢のあるフィールドはモデルから選択肢を取得したり、固定の選択肢をChoiceFieldのchoice
パラメータで初期値として与えるという形式で書かれています。
ですが、この選択肢を動的に作成したいとなった場合はどうしたら良いでしょうか?
Fieldのchoices
プロパティ
Djangoのドキュメントにモデルフィールドリファレンスというページがあり、
ここには、モデルフィールドを含めた、フォームで使用するフィールドについて書かれています。
探してみると、Field.choices
という項があります。
念の為、ChoiceFieldのソースコードも見てみましょう。
class ChoiceField(Field):
(中略)
def _get_choices(self):
return self._choices
def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
if callable(value):
value = CallableChoiceIterator(value)
else:
value = list(value)
self._choices = self.widget.choices = value
choices = property(_get_choices, _set_choices)
(後略)
確かにchoices
というプロパティが存在しています。
では、使ってみましょう。
選択肢を後から追加するChoiceFieldのコード
forms.py
from django import forms
(中略)
class SampleChoiceAddForm(forms.Form):
choice1 = forms.fields.ChoiceField(
required=True,
widget=forms.widgets.Select
)
views.py
from django.shortcuts import render
from django.views import View
from . import forms
(中略)
class SampleChoiceAddView(View):
def get(self, request):
form = forms.SampleChoiceAddForm()
form.fields['choice1'].choices = [
('1', '1番目'),
('2', '2番目'),
('3', '3番目'),
('4', '4番目'),
('5', '5番目'),
]
context = {
'form': form
}
return render(request, 'choice_sample.html', context)
(中略)
sample_choice_add_view = SampleChoiceAddView.as_view()
出力結果
<!DOCTYPE html>
<html lang="ja">
<head>
<title>ChoiceFieldサンプル</title>
</head>
<body>
<form method="POST" aciton="">
<select name="choice1" id="id_choice1">
<option value="1">1番目</option>
<option value="2">2番目</option>
<option value="3">3番目</option>
<option value="4">4番目</option>
<option value="5">5番目</option>
</select>
<input type="hidden" name="csrfmiddlewaretoken" value="xxxxxxxx">
</form>
</body>
</html>
表示
選択肢の後から追加、行けました!