localflavorの登場でしかたなく 、Djangoのnewformsをちょっとさわってみた。
Djangoの素敵な点として、モデルとしての特性は全てModelに記述するというものがあるわけだけど、現時点でのnewformsはどうなのかと。ちょちょいとさわってみただけなので、変かもしれないです。
まず、前提としてnewformsを構成するものたち。
モデルフィールドには型が有り、テーブル生成時やフォームフィールドの型はモデルフィールドから(デフォルトが)決まる。
フォームフィールド生成ロジックはモデルフィールドにある。
oldformsのManipulatorのようなもの。
ユーティリティファンクションで、モデルクラスやモデルインスタンスから生成可能。
newformsが正式なformsとなった際には、汎用ビューにフォームも指定することになると思われる。
今回はウィジェットは無視
で、問題はlocalflavorに日本の郵便番号に対応するフォームフィールドを追加した場合に、どのようにそのフォームフィールドを使用するのかということ。
モデルがこんな感じだったとする。
from django.db import models
from django.contrib.localflavor.jp import models as jp_models
from django.contrib.localflavor.jp import forms as jp_forms
from django.contrib.localflavor.jp.validators import isValidJPPostalCode
from django.contrib.localflavor.jp.jp_prefectures import JP_PREFECTURES
class Address(models.Model):
name = models.CharField(maxlength=50)
postalcode = models.CharField(validator_list=isValidJPPostalCode, maxlength=8)
pref = models.CharField(maxlength=16, choices=JP_PREFECTURES)
models.CharFieldを利用すると、フォームではnewforms.CharFieldが利用される。
ちなみに、現時点ではvalidator_listやchoicesを用いたバリデーションがnewformsでは行われない。
django.newforms.form_for_modelのformfield_callbackを使ってみる
formfield_callbackは、デフォルトではmodels.XxxField.formfieldを呼び出してnewforms.XxxFieldを返 すようになっている。
from django import newforms as forms
from addressbook.address.models import Address
from django.contrib.localflavor.jp import forms as jp_forms
from django.contrib.localflavor.jp.validators import isValidJPPostalCode
def zip_field(f):
if f.name == 'postalcode':
return jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)
return f.formfield()
AddressForm = forms.form_for_model(Address, formfield_callback=zip_field)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
ヒドス
気を取り直して、django.newforms.form_for_modelのformにカスタムフォームを突っ込んでみる
カスタムフォームには、newforms.XxxField生成の振る舞いを変えたいものだけを定義すれば良い。
class AForm(forms.Form):
postalcode = jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)
AddressForm = forms.form_for_model(Address, form=AForm)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
んー。models.XxxFieldを定義した方がスマートだよねぇ。ここだけ振る舞いを変えるならまだしも、Addressモデルのpos talcodeは間違いなく郵便番号系のフィールドを使うんだから…。
Manipulator風にやってみる!
AddressForm = forms.form_for_model(Address)
AddressForm.base_fields['postalcode'] = jp_forms.JPPostalCodeField(postal_validator= isValidJPPostalCode)
data = {'name': 'test', 'postalcode': '251-003', 'pref': 'kanagawa'}
f = AddressForm(data)
f.is_valid()
うぬんうぬうぬorz