.. _ref-forms-api: ============= フォーム API ============= :revision-up-to: 11321 (1.1) unfinished .. currentmodule:: django.forms .. admonition:: このドキュメントについて このドキュメントでは、 Django のフォーム API の細かい部分を解説していま す。まずは :ref:`フォーム処理入門 ` を先に読んでく ださい。 .. _ref-forms-api-bound-unbound: 束縛フォームと非束縛フォーム ------------------------------- フォームのインスタンスには、何らかのデータの集まりが結び付いた **束縛 (bound) フォーム** と、そうでない **非束縛 (unbound) フォーム** があ ります。 * データと **結び付いている** フォームは、データを検証機能する機能と、 フォームを HTML にレンダリングするときにデータを HTML 形式で表示する 機能をあわせ持っています。 * データと **結び付いていない** フォームには検証機能はありません (検証 すべきデータがないから当然ですね!) が、空のフォームを HTML としてレン ダリングする機能は備えています。 非束縛フォームのインスタンスを生成するには、単にフォームクラスのインスタン ス化を行います:: >>> f = ContactForm() フォームにデータを結び付けるには、データの入った辞書をフォームクラスのコン ストラクタの第一引数に渡します:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', ... 'sender': 'foo@example.com', ... 'cc_myself': True} >>> f = ContactForm(data) この辞書の中では、キーは各フィールドの名前であり、フォームクラスの各属性に 対応しています。値は検証すべきデータです。通常、値は文字列にしますが、必ず しも文字列でなくてかまいません。値にどんなデータ型を指定指定できるかは、フィー ルドの型に依存します。 .. attribute:: Form.is_bound 実行時に束縛フォームと非束縛フォームを区別したければ、フォームの :attr:`~Form.is_bound` 属性を調べてください:: >>> f = ContactForm() >>> f.is_bound False >>> f = ContactForm({'subject': 'hello'}) >>> f.is_bound True 空の辞書を渡すと、空のデータの入った *束縛フォーム* を返します:: >>> f = ContactForm({}) >>> f.is_bound True 束縛フォームのインスタンスに入っているデータに何らかの変更を加えたい場合や、 束縛フォームを変換して、何らかのデータの入った非束縛フォームにしたい場合に は、新たにフォームインスタンスを生成してください。フォームインスタンス内の データを変更する方法はありません。一度フォームインスタンスを生成したら、デー タの有無に関わらず、インスタンス内のデータは変更不能だと考えてください。 フォームを使ってデータを検証する -------------------------------- .. method:: Form.is_valid() フォームオブジェクトの主要な役割はデータの検証です。束縛フォームのインスタ ンスに対して :meth:`~Form.is_valid()` メソッドを呼び出すと、データの検証を 行って、その結果をブール値で返します:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', ... 'sender': 'foo@example.com', ... 'cc_myself': True} >>> f = ContactForm(data) >>> f.is_valid() True 無効なデータを入れてみましょう。例えば、 ``subject`` を空にしてみます (フィールドは全てデフォルトで必須なためエラーになります)。また、 ``sender`` に不正なメールアドレス情報を入れてみます:: >>> data = {'subject': '', ... 'message': 'Hi there', ... 'sender': 'invalid e-mail address', ... 'cc_myself': True} >>> f = ContactForm(data) >>> f.is_valid() False .. attribute:: Form.errors :attr:`~Form.errors` という属性にアクセスすると、エラーメッセージの入った辞 書を参照できます:: >>> f.errors {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']} この辞書では、フィールド名がキーに、エラーメッセージを表す Unicode 文字列のリ ストが値になっています。エラーメッセージがリストになっているのは、一つのフィー ルドに対して複数のエラーが存在し得るからです。 :meth:`~Form.is_valid()` を呼ばなくても :attr:`~Form.errors` にはアクセスで きます。 :meth:`~Form.is_valid()` を呼び出すか、 :attr:`~Form.errors` に最 初にアクセスした時点で、フォームのデータが自動的に検証されます。 :attr:`~Form.errors` や :meth:`~Form.is_valid()` に何度アクセスしても、検証 のルーチンはたった一度しか呼ばれません。別の見方をすれば、検証の処理には副 作用があり、その副作用はたった一度しか呼び出されないということです。 非束縛フォームの動作 ~~~~~~~~~~~~~~~~~~~~ データを含まないフォームに対して "cleaned" を実行しても無意味でしかありませ んが、参考までに非束縛フォームに対して行ったときの動作を示しておきます:: >>> f = ContactForm() >>> f.is_valid() False >>> f.errors {} Dynamic initial values ---------------------- .. attribute:: Form.initial Use ``initial`` to declare the initial value of form fields at runtime. For example, you might want to fill in a ``username`` field with the username of the current session. To accomplish this, use the ``initial`` argument to a ``Form``. This argument, if given, should be a dictionary mapping field names to initial values. Only include the fields for which you're specifying an initial value; it's not necessary to include every field in your form. For example:: >>> f = ContactForm(initial={'subject': 'Hi there!'}) These values are only displayed for unbound forms, and they're not used as fallback values if a particular value isn't provided. Note that if a ``Field`` defines ``initial`` *and* you include ``initial`` when instantiating the ``Form``, then the latter ``initial`` will have precedence. In this example, ``initial`` is provided both at the field level and at the form instance level, and the latter gets precedence:: >>> class CommentForm(forms.Form): ... name = forms.CharField(initial='class') ... url = forms.URLField() ... comment = forms.CharField() >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) >>> print f Name: Url: Comment: 「クリーニング済み」のデータにアクセスする ------------------------------------------ フォームクラスの各フィールドには、データの検証だけでなく、「クリーニング」 を行う役割もあります。データのクリーニングとは、データを一貫性のある書式に 正規化することです。データのクリーニングはとても素晴らしい機能で、クリーニ ングを行うと、ユーザがフィールドに色々な形式でデータを入力しても、常に一貫 性を持った出力を得られます。 例えば、 ``DateField`` はデータを Python の ``datetime.date`` オブジェクト に正規化します。フィールドの値は、 ``'1994-07-15'`` のような形式の文字列で も、 ``datetime.date`` オブジェクトでも、その他の形式でも、 ``DateField`` は有効なデータであるかぎり、常に出力を ``datetime.date`` オブジェクトで正規 化します。 データセットの入ったフォームインスタンスを生成して検証を行うと、 ``cleaned_data`` 属性を介してクリーニング済みのデータにアクセスできるようにな ります:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', ... 'sender': 'foo@example.com', ... 'cc_myself': True} >>> f = ContactForm(data) >>> f.is_valid() True >>> f.cleaned_data {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} .. versionchanged:: 1.0 ``cleaned_data`` 属性は、以前のリリースでは ``clean_data`` と呼ばれてい ました。 ``CharField`` や ``EmailField`` のようなテキストベースのフィールドは、常に 入力を Unicode 文字列に変換します。エンコーディングに関する解説は、このドキュ メントの後の方でカバーする予定です。 データが *まだ検証されていない* 場合、フォームインスタンスには ``cleaned_data`` 属性がありません:: >>> data = {'subject': '', ... 'message': 'Hi there', ... 'sender': 'invalid e-mail address', ... 'cc_myself': True} >>> f = ContactForm(data) >>> f.is_valid() False >>> f.cleaned_data Traceback (most recent call last): ... AttributeError: 'ContactForm' object has no attribute 'cleaned_data' フォームを生成するときに追加の値を渡した場合でも、 ``cleaned_data`` の中に 入るキーは、フォーム内で定義されているフィールド *だけ* です。以下の例でも、 ``ContactForm`` のコンストラクタに追加のフィールドデータを渡していますが、 ``cleaned_data`` が返すのは ``ContactForm`` で定義されているフィールドだけで す:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', ... 'sender': 'foo@example.com', ... 'cc_myself': True, ... 'extra_field_1': 'foo', ... 'extra_field_2': 'bar', ... 'extra_field_3': 'baz'} >>> f = ContactForm(data) >>> f.is_valid() True >>> f.cleaned_data # Doesn't contain extra_field_1, etc. {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} ``cleaned_data`` には、 ``Form`` 内で定義されている *全ての* フィールドのキー と値が入ります。フォームに渡したデータに、必須でないフィールドの値が入って いない場合でもです。下の例では、データ辞書には ``nick_name`` フィールドの値 が入っていませんが、 ``cleaned_data`` には空の値が入っています:: >>> class OptionalPersonForm(Form): ... first_name = CharField() ... last_name = CharField() ... nick_name = CharField(required=False) >>> data = {'first_name': u'John', 'last_name': u'Lennon'} >>> f = OptionalPersonForm(data) >>> f.is_valid() True >>> f.cleaned_data {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} この例で、 ``cleaned_data`` の中の ``nick_name`` は空文字列なのは、 ``nick_name`` が ``CharField`` であり、 ``CharField`` は空の値を空文字列と みなすからです。各フィールドタイプは「空の」値が設定されています。例えば、 ``DateField`` の場合、空の値は空文字列ではなく ``None`` になります。 空の値を持ったフィールドの詳しい挙動は、「組み込みフィールドクラス」の節の 各フィールドの説明中の「空のフォームデータに対する値」の項目を参照してくだ さい。 個別のフォームフィールド (フィールド名ごと) やフォーム全体 (複数フィールド の組み合わせ) に対してバリデーションを実現するコードを書けます。詳しくは、 :ref:`ref-forms-validation` を参照してください。 フォームを HTML として出力する ------------------------------ フォームオブジェクトの二つ目の仕事は、フォームの HTML へのレンダリングです。 フォームを HTML として出力するには、フォームをインスタンス化して、 ``print`` で出力します:: >>> f = ContactForm() >>> print f 束縛フォームの場合、フォームのデータは適切な形で HTML 出力されます。例えば、 フィールドが ```` で表される場合、データは ``value`` 属 性の中に出力されます。フィールドが ```` であれば、 必要に応じて ``checked="checked"`` が入ります:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', ... 'sender': 'foo@example.com', ... 'cc_myself': True} >>> f = ContactForm(data) >>> print f デフォルトの出力は 2 カラムの HTML テーブルになり、各フィールドが一つの ```` タグの中に収まります。以下の点に注意してください: * 柔軟性をもたせるために、出力中には ```` と ``
`` タグが 入っていません。また、 ``
`` と ``
`` や、 ```` もありません。これらのタグは自分で入れる必 要があります。 * 各フィールドタイプには、それぞれデフォルトの HTML 表現があります。 ``CharField`` や ``EmailField`` は ```` で表され、 ``BooleanField`` は ```` になります。とはいえ、 これらは便利なデフォルト値にすぎません。ウィジェット (widget) を使え ば、フィールドの表現にどのような HTML を使うかを指定できます。これに ついては後で説明する予定です。 * 各タグの ``name`` 属性は ``ContactForm`` クラスの属性名から直接取り出 して使われます。 * ``'Subject:'``, ``'Message:'``, ``'Cc myself:'`` といった各フィール ドのテキストラベルは、フィールド名のアンダースコアを全てスペースに変 換し、先頭の文字を大文字にして生成します。これもまたデフォルト値にす ぎず、手動でもラベルを設定できるようになっています。 * 各テキストラベルは HTML の ``