LoginSignup
27
21

More than 3 years have passed since last update.

【Python】【Django】ChoiceFieldの使い方と選択肢の追加方法

Last updated at Posted at 2019-11-03

概要

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>

表示

表示結果1.png

時間のかかった箇所

  • 選択肢を後から追加する方法

選択肢を後から追加する方法

公式チュートリアルや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>

表示

表示結果2.png

選択肢の後から追加、行けました!

27
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
21