読者です 読者をやめる 読者になる 読者になる

DjangoのformsでHTML5の新要素を使う

最近のweb業界を一番にぎわせてるのは、mixiアプリなんかではなくHTML5だと思ったりしてます。こんばんは
HTML5はvideoタグでflashいらずとか、canvasタグでアニメーションとかに目が行きがちですが、HTML5ではformに新要素が加わって地味に便利になってたりするのです。

form要素の何が変わったの?

ざっと言うと、検索用やemail用、URL用、時間用のフォームなどの指定ができるようになりました。。
また新たな属性が増え、未入力状態の入力フィールドに表示されるヒント情報が出せるようになったりもしてます。以下の様な感じです。

<input type="text" placeholder="input me">

Javascriptを知らなくても簡単に記述できるので、この記事とか涙目ですね!*1


HTML5の詳しい解説記事は下記を参考にしてください
【特集】詳解! HTML 5と関連APIの最新動向 - 新タグ&API編 (5) 大幅に強化されたフォーム要素 | エンタープライズ | マイナビニュース

Djangoでフォームを扱う場合はどうするんだっけ?

Djangoにはformを扱うdjango.formsという便利なライブラリが存在します。
これはどんなものかと言うと、出力したいフォームをモデルとして表現することで、フォームの出力、バリデーション、エラー表示を簡単に行おうと言うものです。以下例

from django import forms

#簡単なユーザープロフィールの例
class Profile(forms.Form):
    name = forms.CharField(max_length=100)
    url = forms.URLField(verify_exists=True)
    email = forms.EmailField(max_length=200)

p = Profile()
print p

結果は下記のようなHTMLが出力されます

<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="100" /></td></tr>
<tr><th><label for="id_url">Url:</label></th><td><input type="text" name="url" id="id_url" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input id="id_email" type="text" name="email" maxlength="200" /></td></tr>

ちなみにテーブル以外の出力方法とかもあるんですが、今回は使い方とかは省略します。リファレンスの方が100倍詳しく、そしてわかりやすく書いてるのでそっちを見てください
http://djangoproject.jp/doc/ja/1.0/topics/forms/index.html

さらに大体の場合はmodelとformを関連づけるmodelformを使うのが一般的だと思いますが、これまた今回はめんどくさいので省略。

話を戻しますが、この出力されたHTMLをなんとかしてHTML5の新要素を含めたフォームに変更したいところです。
下記のようなHTMLが出力されればとりあえず成功とします

<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="100" placeholder="input name" /></td></tr>
<tr><th><label for="id_url">Url:</label></th><td><input type="url" name="url" id="id_url" placeholder="input url" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input id="id_email" type="text" name="email" maxlength="200" placeholder="input email" /></td></tr>
Widegetを使う

Djangoにはformの出力をいじれるWidegetクラスと言うものが存在します。
先ほどのモデルは下記のように書くのと同じ意味です。CharFieldやURLFieldのデフォルトwidgetはTextInputになっています。

class Profile(forms.Form):
    name = forms.CharField(max_length=100,widget=forms.TextInput())
    url = forms.URLField(verify_exists=True,widget=forms.TextInput())
    email = forms.EmailField(max_length=200,widget=forms.TextInput())

というわけで、TextInputクラスの中身を見てみたらたったこれだけでした

class TextInput(Input):
    input_type = 'text'

素人考えでも、input_typeを"url"や"email"にするだけで大丈夫な気がしてきます
というわけでHTML5に対応したフォームのモデルは下記のようになりました

フォームクラス
from django.forms import widgets
from django import forms

class URLInput(widgets.Input):
    input_type = "url"
  
class EmailInput(widgets.Input):
    input_type = "email"
 
class Profile(forms.Form):
    name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={"placeholder":"input name"}))
    url = forms.URLField(verify_exists=True,widget=URLInput(attrs={"placeholder":"input url"}))
    email = forms.EmailField(max_length=200,widget=EmailInput(attrs={"placeholder":"input email"}))

p = Profile()
print p
出力結果
<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" placeholder="input name" name="name" maxlength="100" /></td></tr>
<tr><th><label for="id_url">Url:</label></th><td><input type="url" placeholder="input url" name="url" id="id_url" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="None" placeholder="input email" name="email" id="id_email" /></td></tr>


対応が糞簡単だったので、そのうちHTML5が浸透したらDjango本体にも組み込まれるんじゃないですかね?
今これらに対応したところで、恩恵を受けるのはOpera10だけなので対応するうまみがほとんどないですけど!
個人的にはOpera10はHTML5よりCSS3をがんばって欲しいです。border-radiusが使えないと人間が死にます。

*1:でもplaceholderに対応したブラウザは少なかったり…