diadia

興味があることをやってみる。自分のメモを残しておきます。

formのウィジェットについて

ウィジェットの理解を深めない限り、forms.ModelFormやforms.Formの利用したとて、フォーム画面が残念な結果になってしまう。

見た目の良いフォーム画面を作るには、htmlでフォーム画面を作成するか、ModelFormやFormのウィジェットを使いこなせる様になる必要がある。

 

今回はウィジェットを使いこなせるようになるために少しずつ理解を深める一歩にしようと思う。今回ここを軽くまとめてみたが、これができるだけで見た目がガラッと変わる。

 

https://docs.djangoproject.com/ja/2.2/topics/forms/

https://docs.djangoproject.com/ja/2.2/ref/forms/widgets/

そもそもウィジェットとは?

まだはっきりと分かっていない。

 

http://e-words.jp/w/%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83%88.html

これによるとユーザーの操作面に関する概念だろう。より操作しやすくなるために関わるものとしてまずはおさえておく。それを裏付ける例がこれだ。 

https://docs.djangoproject.com/ja/2.2/ref/forms/widgets/#specifying-widgets

from django import forms

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField(widget=forms.Textarea)

本来ならcommentはCharFieldなのでTextInputのウィジェットをフォーム入力欄としてユーザーは利用しなければならない。TextInputは横一列のフォーム入力欄で、コメントがフォーム欄に入り切らない文字数の場合には使いにくくなってしまう。そこでCharfieldであるにもかかわらず、Textareaのフォーム欄に変更したいという要望がある。そのときにCharField()の引数としてwiget=forms.TextareaにするとTextareaに変更することができるというわけだ。

要するに操作面が向上したと言えるわけだ。

 

ウィジェットインスタンスをカスタマイズする

https://docs.djangoproject.com/ja/2.2/ref/forms/widgets/#customizing-widget-instances

 

ウィジェットCSSを適用することができる。今までは本来適用される予定のウィジェットを変更することができることを紹介した。今回はウィジェットに色をつけたり、見た目を良くするというCSSを適用できる論点だ。

 

これらを実現するためには、ウィジェットを作成するときに Widget.attrs 引数を使います:

例えばBootstrap4のform-controlを反映させたい場合以下のようになる。

class CommentModelForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ("name","url","comment")
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            self.field["name"].widget.attrs["class"] = "form-control"
            self.field["url"].widget.attrs["class"] = "form-control"
            self.field["comment"].widget.attrs["class"] = "form-control"
        

その他ウィジェットを編集する方法は以下のようになる。なお、参考資料は以下である。
https://docs.djangoproject.com/ja/2.2/ref/forms/api/#accessing-the-fields-from-the-form

 

def __init__(self, *args, **kwargs):
   super().__init__(*args, **kwargs)
   for field in self.fields.values():
        self.field["name"].required = True  #必須項目のフォームに変更する
        self.field["url"].label = "URL"  #ユーザ視点でフォームの入力名が変わる。
        self.field["comment"].widget.attrs["placeholder"] = "コメントを書いてください。"