Djangoのforms.pyが提供するフォームテンプレートは使わない
Djangoのforms.pyはユーザーから受け取った値のバリデーションだけでなく、フォームのテンプレートも提供してくれる。(widgetを使うなどしてクラス名やHTMLタグの指定ができる)
しかし、私はこのforms.pyの提供するフォームのテンプレートは使わない。本記事ではその理由を列挙する
理由1:フロントサイドとサーバーサイドの分業問題
そもそも、テンプレートの開発はフロントサイド開発者のすることである。それが投稿用のフォームでも例外ではないと私は思う。
故に、本来テンプレートで指定するべきクラス名やHTMLのタグをforms.py
で決めてしまうのは、フロントとサーバーの分業ができていないと言えよう。
前もって相談すれば良いという意見もあるが、name属性だけと、クラス名とHTMLタグの2つでは相談の負担は違うと思う。特にクラス名は状況に応じて変わる可能性もある。変更があるたびにサーバーサイド側の開発者に了承を得ているようでは納期遅れになるだろう。
一方でname属性は一度モデルを作ってしまえば殆ど変わることはない。つまり、基本的に一回だけフロントサイドの開発者に提示すればそれで済むのだ。
理由2:HTMLの構成、クラス名を自由に指定できない
9割ほど原因はこれである。これのせいで、フォームのユーザビリティを著しく低下させてしまう。
まずは、『【Django】一対多、多対多のリレーションでforms.pyを使ったバリデーションとフォームを表示』にて掲載している下記画像をご覧いただきたい。
これは多対多のリレーションを含むモデルを継承したforms.py
のテンプレートにそのまま表示させている。ご覧の通り、アレルギー選択欄が扱いづらいものになっている。
これは複数選択する時、Ctrlキーを押しながらクリックをしなければならない(※ただしブラウザによって挙動は異なる、Firefoxにて確認済み)。記事のリンク先にコードがあるので、実際に動かしてみるとよいだろう。
この状態で、forms.py
のテンプレートを使わず、name属性だけ合わせて、自前で作るとこうなる。
複数選択をinput
タグのcheckbox
にしたため、それぞれが独立して複数選択がやりやすくなっている。前者のようにselect
タグにmultiple
属性を指定しただけのものと違って、その操作性は雲泥の差である。
このように普通の人がCtrlキーを押しながらクリックする作業は負担であり、まっとうなエンジニアであればそんなことを強要してはならないと私は思う。
日付入力時のそれも同様である。日付入力はなるべくflatpickr
等のライブラリを使用して日付選択をしやすくさせたほうが良いだろう。
【日付入力】flatpickrの実装方法(ロケール日本語化、日時入力対応化)
理由3:そもそもHTML的に誤りである(SEO上の問題?)
ビューがコンテキストにフォームクラスのインスタンスを渡してレンダリングする時、フォームのインスタンスは以下のテンプレート変数を使ってフォームのHTMLを描画できる。
{{ form.as_p }}
{{ form.as_ul }}
{{ form.as_table }}
いずれも、input
タグやselect
タグなどをp
タグ(.as_p
)、ul
タグ(.as_ul
)、table
タグ(.as_table
)で囲んで表示させる。ul
タグならまだわかるが、p
タグで囲むのはHTML的に問題があるのではなかろうか?
結論
一応、widget
を使えばクラス名やHTMLタグをforms.py
から指定することもできるが、そんな回りくどいことをするぐらいだったらname属性だけ帳尻を合わせてテンプレート側で1から作ったほうが簡単。
何より、装飾に必要なクラス名が変わるたびに、サーバーサイドの開発者に許可を得ていたら納期遅れ必至でしょう。
テキストエリアも単にtextarea
タグを使うのではなく、div
タグにcontenteditable
属性をtrue
にして代用する方法もある。実際にTwitterでは後者が使われている模様。