1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Django FormのChoiceFieldでBootstrapのbtn-groupを使いたい

Last updated at Posted at 2020-10-07

やりたいこと

キャプチャ.JPG
・こんな感じのことをRadioSelectのwidgetを使ってやりたかった。

環境

  • Django 3.1.2
  • Bootstrap 4.3.1

前提

forms.py
class CustomForm(forms.Form):
    interval = forms.ChoiceField(
        choices=((0, "DAY"), (1, "HOUR"), (2, "MINUTE"),),
        widget=forms.RadioSelect
    )
    ...

こんなFormがあるとして、このintervalを上のようなBootstrapのbtn-groupを使って表示したい。

流れ

  1. settingsを変更しRadioSelectで独自Templateを使えるように。
  2. Templateを調整。
  3. TestFormで独自Templateを設定。

1. 設定の変更

settings.py
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
INSTALLED_APPS [
    ...,
    "django.forms",
]

デフォルトのレンダラーだとtemplates以下のファイルを読み込めないためTemplateSettingに変更。
そして、このままだと今度は組み込みTemplateを読み込めないためINSTALLED_APPSにdjango.formsを追加。

2. 独自Templateの作成。

今回はDjangoデフォルトのものをベースに radio.html と radio_options.html の2種類のTemplateを使う。

widget/radio.html
{% with id=widget.attrs.id %}
    <div{% if id %} id="{{ id }}"{% endif %}
                    class="btn-group btn-group-toggle {% if widget.attrs.class %}{{ widget.attrs.class }}{% endif %}" data-toggle="buttons">
        {% for group, options, index in widget.optgroups %}
            {% for option in options %}
                {% include option.template_name with widget=option %}
            {% endfor %}
        {% endfor %}
    </div>
{% endwith %}
widget/radio_options.html
{% if widget.wrap_label %}<label{% if widget.attrs.id %}
    for="{{ widget.attrs.id }}"{% endif %}
    class="btn btn-sm btn-outline-dark">{% endif %}{% include "django/forms/widgets/input.html" %}
{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}

やっていることはClassの追加とHTMLタグの修正くらい。

3. form.pyの修正

forms.py
class CustomForm(forms.Form):
    interval = forms.ChoiceField(
        choices=((0, "DAY"), (1, "HOUR"), (2, "MINUTE"),),
        widget=forms.RadioSelect
    )
    interval.widget.template_name = "widget/radio.html"
    interval.widget.option_template_name = "widget/radio_options.html"
    ...

[field_name].widget.template_name と option_template_name に作ったTemplateを設定。

完成!

キャプチャ.JPG

Tips

初期値を設定したい。

forms.py
class CustomForm(form.Form):
    def __init__(self, *args, **kwargs):
        super(GiftFormSearch, self).__init__(*args, **kwargs)
        self.initial["interval"] = 0

init内で設定できます。 views.pyで設定したい場合は以下の通り。

views.py
def hogehoge(request):
    ...
    form = CustomForm({"interval": 0})

ただし、inputにcheckedが追加されるだけでClassには何も追加されないため見た目で判別できないことに注意。
クライアント側のjsでとりあえず対応しています。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?