フォーム API¶
このドキュメントについて
このドキュメントでは、Django のフォーム API の詳細について説明します。このドキュメントを読む前に フォームについての概要 を読むことをおすすめします。
バインドされた (bound) フォームとバインドされていない (unbound) フォーム¶
Form
のインスタンスには、データセットに バインドされている (bound な) ものと バインドされていない (unbound な) ものがあります。
データセットに バインドされた
Form
インスタンスであれば、そのデータをバリデーションしたり、HTMLとしてフォームをレンダリングし、HTMLにデータを表示したりすることができます。データセットに バインドされていない
Form
インスタンスでは、(検証するデータがないので)データをバリデーションすることはできませんが、空のフォームをHTMLとしてレンダリングできます。
バインドされていない Form
のインスタンスを作成するには、クラスの初期化を行います。
>>> f = ContactForm()
フォームにデータをバインドするには、辞書型のデータを Form
クラスのコンストラクタの最初のパラメータとして渡します。
>>> data = {
... "subject": "hello",
... "message": "Hi there",
... "sender": "foo@example.com",
... "cc_myself": True,
... }
>>> f = ContactForm(data)
この辞書では、キーは Form
クラスの属性に対応するフィールド名を、値には検証したいデータを指定します。これらは通常文字列ですが、必ずしも文字列型でなくてもかまいません。後ほど解説しますが、渡すデータの型は、 Field
に依存します。
- Form.is_bound¶
実行時にバインドされたフォームインスタンスと、されていないフォームインスタンスを区別する必要があるときは、フォームの is_bound
属性の値を確認してください。
>>> f = ContactForm()
>>> f.is_bound
False
>>> f = ContactForm({"subject": "hello"})
>>> f.is_bound
True
空の辞書を渡すと、データが空の バインドされた フォームが作成されることに注意してください。
>>> f = ContactForm({})
>>> f.is_bound
True
Form
インスタンス内のデータを変更する方法はありません。 一度作成された Form
インスタンスのデータは、その有無に関わらず変更不可能であると考えてください。もし Form
インスタンスにバインドされたデータを変更したい場合や、バインドされていない Form
インスタンスをデータにバインドしたい場合は、別の Form
インスタンスを作成してください。
フォームをデータの検証に使用する¶
- Form.clean()¶
相互に関連のあるフィールドに対して独自のバリデーションを追加する必要がある場合、Form
上で clean()
を実装してください。具体的な使用方法は 互いに依存するフィールドをクリーニングして検証する を参照してください。
- Form.is_valid()¶
Form
オブジェクトの主なタスクは、データの検証です。バインドされた 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 email address",
... "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
- Form.errors¶
errors
属性にアクセスして、エラーメッセージの辞書を取得します。
>>> f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}
この辞書では、キーはフィールド名であり、値はエラーメッセージを表す文字列のリストです。エラーメッセージがリストに格納されているのは、1つのフィールドに複数のエラーメッセージが出力される場合があるからです。
is_valid()
を呼び出す前にも、 errors
にアクセスできます。フォームのデータは、最初に is_valid()
を呼び出すか、 errors
にアクセスした時点で検証されます。
バリデーションのルーチンは、errors
や call is_valid()
を何度呼び出したとしても、最初の一度だけ呼び出されます。これは、バリデーションが副作用を持っている場合、その副作用は一度しか発生しないということを意味します。
- Form.errors.as_data()¶
フィールドとオリジナルの ValidationError
インスタンスをマッピングする dict
を返します。
>>> f.errors.as_data()
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}
code
によりエラーを特定する必要があるときはこのメソッドを使用してください。これによって、エラーメッセージの上書きや、エラーが存在するときのビューでの独自のロジックが作成できるようになります。独自のフォーマット (たとえば XML) でシリアライズするためにも使えます。たとえば、as_json()
は as_data()
を利用しています。
as_data()
の必要性は、後方互換性に起因します。以前は ValidationError
インスタンスは レンダリングされた エラーメッセージが Form.errors
ディクショナリに追加されると同時に消失していました。できれば Form.errors
が ValidationError
インスタンスを保持し、as_
プレフィクスを伴うメソッドがエラーをレンダリングできるのが理想でしたが、Form.errors
内のレンダリングされたエラーメッセージを受け取る可能性があるコードを壊さないために、逆の実装にしなくてはなりませんでした。
- Form.errors.as_json(escape_html=False)¶
エラーをJSONとしてシリアライズしたものを返します。
>>> f.errors.as_json()
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}
デフォルトでは、as_json()
は出力をエスケープしません。フォームビューへのAJAXリクエストなど、クライアントがレスポンスを解釈しエラーをページに挿入する場合には、クロスサイトスクリプティング攻撃の可能性を避けるために、クライアント側で結果をエスケープする必要があります。これはJavaScriptで、 element.textContent = errorText
、またはjQueryの $(el).text(errorText)
(.html()
関数ではなく) を使用することで実行できます。
何らかの理由でクライアントサイドのエスケープを使いたくない場合は、 escape_html=True
を設定すればエラーメッセージがエスケープされ、HTMLで直接使用できるようになります。
- Form.errors.get_json_data(escape_html=False)¶
JSON にシリアライズできる形式のエラーを辞書として返します。 Form.errors.as_json()
はシリアライズされた JSON を返しますが、これはシリアライズされる前のエラーデータを返します。
escape_html
パラメータは、 Form.errors.as_json()
で説明されているように動作します。
- Form.add_error(field, error)¶
このメソッドは、Form.clean()
メソッド内またはフォーム全体の外部から特定のフィールドにエラーを追加することを可能にします。たとえば、ビューから追加することもできます。
field
引数にはエラーを追加したいフィールド名を指定します。この値が None
の場合、 Form.non_field_errors()
によって返されるようなフィールドによらないエラーとして扱われます。
フォームエラーを定義するときのベストプラクティスとして、 error
引数は文字列もしくは、できれば ValidationError
のインスタンスを指定します。フォームエラーの定義時のベストプラクティスについては、 ValidationError を発生させる を参照してください。
Form.add_error()
は cleaned_data
からフィールドを自動的に削除してしまうことに注意してください。
- Form.has_error(field, code=None)¶
このメソッドは指定したフィールドが特定の code
のエラーを持つか否かを真偽値で返します。code
が None
の場合、そのフィールドにエラーが一つもない場合に True
を返します。
フィールドによらないエラー (non-field errors) の有無を確認したい場合は、field
引数に NON_FIELD_ERRORS
を渡します。
- Form.non_field_errors()¶
このメソッドは、特定のフィールドに関連付けられていない Form.errors
からのエラーリストを返します。これには、Form.clean()
で発生した ValidationError
や、Form.add_error(None, "...")
を使用して追加されたエラーが含まれます。
バインドされていないフォームの動作¶
フォームにデータがない場合、フォームの検証は意味をなしません。一応記載しておくと、バインドされていないフォームでは次のような結果になります。
>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}
フォームの初期値¶
- Form.initial¶
initial
を使うことで、実行時にフォームの初期値を設定できます。たとえば、 username
フォームを埋めるのに、現在のセッションの username を使うことができます。
これを実現するには、 Form
の初期化時に initial
引数を使用します。この引数には、フィールド名と初期値のマッピングした辞書を指定します。初期値を指定するフィールドだけを含めればよく、フォーム内のすべてのフィールドを含める必要はありません。以下に例を示します。
>>> f = ContactForm(initial={"subject": "Hi there!"})
これらの値はバインドされていないフォームに表示されるだけです。値が入力されなかった場合の、フォールバックされる値として使われることはありません。
Field
において initial
を定義 した上で Form
をインスタンス化するときに initial
を指定した場合、後者の initial
が優先されます。以下の例では、フィールドレベルとフォームインスタンスレベルの両方で initial
が提供され、後者が優先されます。
>>> from django import forms
>>> 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)
<div>Name:<input type="text" name="name" value="instance" required></div>
<div>Url:<input type="url" name="url" required></div>
<div>Comment:<input type="text" name="comment" required></div>
- Form.get_initial_for_field(field, field_name)¶
フォームフィールドの初期データを返します。データは、存在する場合は Form.initial
から取得し、それ以外の場合は Field.initial
を参照します。呼び出し可能な値は評価されます。
BoundField.initial
はよりシンプルなインターフェースを持っているため、get_initial_for_field()
よりも BoundField.initial
の使用が推奨されます。また、get_initial_for_field()
とは異なり、BoundField.initial
はその値をキャッシュします。これは、戻り値が変わる可能性がある呼び出し可能オブジェクト (例: datetime.now
や uuid.uuid4
) を扱う場合に特に便利です。
>>> import uuid
>>> class UUIDCommentForm(CommentForm):
... identifier = forms.UUIDField(initial=uuid.uuid4)
...
>>> f = UUIDCommentForm()
>>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
>>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
>>> # Using BoundField.initial, for comparison
>>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
>>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
どのフォームデータが変更されたかをチェックする¶
- Form.has_changed()¶
フォームデータが初期値から変更されたかどうかをチェックしたい場合は、 has_changed()
メソッドを使います。
>>> data = {
... "subject": "hello",
... "message": "Hi there",
... "sender": "foo@example.com",
... "cc_myself": True,
... }
>>> f = ContactForm(data, initial=data)
>>> f.has_changed()
False
フォームが送信された場合、比較ができるようにフォームを再構築して元のデータを提供します:
>>> f = ContactForm(request.POST, initial=data)
>>> f.has_changed()
has_changed()
は、 request.POST
が initial
で提供されたデータと異なる場合、 True
を返し、同じであれば False
を返します。この結果は、それぞれのフィールドで Field.has_changed()
を呼ぶことで計算されます。
- Form.changed_data¶
changed_data
属性は、フォームにバインドされたデータ (ふつうは request.POST
) の値が initial
で提供されたものと異なるとき、そのフィールド名のリストを返します。データが変更されていない場合は、空のリストを返します。
>>> f = ContactForm(request.POST, initial=data)
>>> if f.has_changed():
... print("The following fields changed: %s" % ", ".join(f.changed_data))
...
>>> f.changed_data
['subject', 'message']
フォームからフィールドにアクセスする¶
- Form.fields¶
Form
インスタンスのフィールドには、その fields
属性からアクセスできます。
>>> for row in f.fields.values():
... print(row)
...
<django.forms.fields.CharField object at 0x7ffaac632510>
<django.forms.fields.URLField object at 0x7ffaac632f90>
<django.forms.fields.CharField object at 0x7ffaac3aa050>
>>> f.fields["name"]
<django.forms.fields.CharField object at 0x7ffaac6324d0>
フィールドと BoundField
、 Form
インスタンスを変更することで、フォーム内でのフィールドの表示方法を変更できます。
>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
>>> f["subject"].label = "Topic"
>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Topic:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
base_fields
属性を変更しないように注意してください。この変更は、同じPythonプロセス内のすべての後続の ContactForm
インスタンスに影響を与えます。
>>> f.base_fields["subject"].label_suffix = "?"
>>> another_f = ContactForm(auto_id=False)
>>> another_f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject?</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
"clean" なデータにアクセスする¶
- Form.cleaned_data¶
Form
クラスの各フィールドは、データの検証だけでなく、それを「クリーニング」する – すなわち、データを一貫した形式に正規化する役割も担っています。これは素晴らしい機能で、各フィールドにおいて、様々な形式で入力されるデータから、常に整合性のある出力を得ることができます。
たとえば、 DateField
はインプットを Python の datetime.date
オブジェクトに正規化します。たとえ '1994-07-15'
という形式の文字列で渡そうが、 datetime.date
オブジェクトを渡そうが、他の様々な形式で渡そうが、それが検証にパスする限り DateField
はいつも datetime.date
オブジェクトに正規化します。
Form
インスタンスを作成し、データをセットして検証した後は、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': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
CharField
や EmailField
といったテキストベースのフィールドは、入力を文字列に正規化します。暗黙的な文字エンコードの動作については、後のドキュメントでカバーします。
もしデータが検証に合格 しなかった 場合、 cleaned_data
の辞書には有効なフィールドのみが含まれます。
>>> data = {
... "subject": "",
... "message": "Hi there",
... "sender": "invalid email address",
... "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}
たとえ Form
を定義する際に追加のデータを渡しても、 cleaned_data
には Form
で定義されたフィールドのキー のみ が含まれます。この例では ContactForm
のコンストラクタに追加のフィールドを渡していますが、 cleaned_data
にはフォームのフィールドのみが含まれます。
>>> 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': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
Form
の検証に合格した場合、 任意入力のフィールドのデータが一部含まれていなかったとしても、 すべての フィールドのキーと値が含まれています。この例では、渡したデータに nick_name
フィールドの値は含まれていませんが、 cleaned_data
には空の値が含まれています。
>>> from django import forms
>>> class OptionalPersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
... nick_name = forms.CharField(required=False)
...
>>> data = {"first_name": "John", "last_name": "Lennon"}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}
In this above example, the cleaned_data
value for nick_name
is set to an
empty string, because nick_name
is CharField
, and CharField
s treat
empty values as an empty string. Each field type knows what its "blank" value
is -- e.g., for DateField
, it's None
instead of the empty string. For
full details on each field's behavior in this case, see the "Empty value" note
for each field in the ビルトインの Field クラス section below.
特定のいくつかの (フォーム名に基づく) フォームフィールドまたは (さまざまなフィールドの組み合わせを考えて) フォーム全体に対してのバリデーションを行うコードを書くこともできます。これについての詳細は、 フォームとフィールドのバリデーション を見てください。
フォームをHTMLとしてアウトプットする¶
Form
オブジェクトの2番目のタスクは、自身をHTMLとしてレンダリングすることです。それを行うには print
します。
>>> f = ContactForm()
>>> print(f)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject"></div>
<div><label for="id_message">Message:</label><input type="text" name="message" required id="id_message"></div>
<div><label for="id_sender">Sender:</label><input type="email" name="sender" required id="id_sender"></div>
<div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself"></div>
フォームがデータにバインドされている場合、HTMLの出力にはそのデータが適切に含まれます。たとえば、フィールドが <input type="text">
で表される場合、データは value
属性に含まれます。フィールドが <input type="checkbox">
で表される場合、HTMLには必要に応じて checked
が含まれます。
>>> data = {
... "subject": "hello",
... "message": "Hi there",
... "sender": "foo@example.com",
... "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> print(f)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
<div><label for="id_message">Message:</label><input type="text" name="message" value="Hi there" required id="id_message"></div>
<div><label for="id_sender">Sender:</label><input type="email" name="sender" value="foo@example.com" required id="id_sender"></div>
<div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></div>
このデフォルトの出力は、各フィールドを <div>
で囲みます。以下の点に注意してください。
柔軟性のために、出力には
<form>
と</form>
のタグや<input type="submit">
のタグは含まれていません。これらは各自で追加するようにしてください。それぞれのフィールドタイプはデフォルトの HTML 表現を持っています。
CharField
は<input type="text">
で、EmailField
は<input type="email">
で表現され、BooleanField(null=False)
は<input type="checkbox">
で表現されます。これらは単なる実用的なデフォルトであり、あるフィールドにどの HTML を使うかは、すぐ後で説明するウィジェットを使って指定できます。HTML のそれぞれのタグの
name
は、ContactForm
クラスの属性名から直接とられます。それぞれのフィールドのテキストラベル、たとえば
'Subject:'
,'Message:'
,'Cc myself:'
は、フィールド名のアンダースコアをスペースに変換し、頭文字を大文字に変換して生成されます。これらもまた単なる実用的なデフォルトです; 手動でラベルを指定することもできます。それぞれのテキストラベルは HTML
<label>
タグで囲まれており、id
を通して適切なフォームフィールドを指しています。id
は、フィールド名に'id_'
を前置することで生成されます。id
属性と<label>
タグは、ベストプラクティスに従ってデフォルトでアウトプットにインクルードされますが、この挙動も変更できます。出力はHTML5の構文を使用し、
<!DOCTYPE html>
をターゲットにしています。例えば、checked='checked'
のXHTMLスタイルではなくchecked
のようなブール属性を使用します。
フォームを print
するときは <div>
がデフォルトの出力スタイルですが、独自のフォームテンプレートを使用して、出力をカスタマイズできます。このテンプレートは、サイト全体、フォームごと、またはインスタンスごとに設定できます。詳細は、 再利用可能なフォームテンプレート を参照してください。
デフォルトのレンダリング¶
フォームを print
するときのデフォルトのレンダリングでは、次のメソッドと属性が使用されます。
template_name
¶
- Form.template_name¶
フォームを文字列に変換するときにレンダリングされるテンプレートの名前です。例えば、 print(form)
やテンプレート内の {{ form }}
などで使用されます。
デフォルトでは、レンダラーの form_template_name
の値を返すプロパティです。特定のフォームクラスに対してそれを上書きするために、文字列型のテンプレート名として設定できます。
render()
¶
- Form.render(template_name=None, context=None, renderer=None)¶
renderメソッドは、 __str__
だけでなく、 Form.as_div()
、 Form.as_table()
、 Form.as_p()
、および Form.as_ul()
メソッドによって呼び出されます。すべての引数はオプションであり、デフォルトは次のとおりです。
template_name
:Form.template_name
context
:Form.get_context()
が返す値renderer
:Form.default_renderer
が返す値
template_name
を渡すことで、単一の呼び出しに使用されるテンプレートをカスタマイズできます。
get_context()
¶
- Form.get_context()¶
テンプレートをレンダリングするためのコンテキストを返します。
利用可能なコンテキストは次のとおりです。
form
: バインドされたフォーム。fields
: 隠されたフィールドを除く、すべてのバインドされたフィールド。hidden_fields
: すべての隠されたバインドフィールド。errors
: フォームの非フィールド関連または非表示フィールド関連の全エラー。
template_name_label
¶
- Form.template_name_label¶
テンプレートは、 BoundField.label_tag()
/legend_tag()
を呼び出す際に使用されるフィールドの <label>
をレンダリングするために使用されます。この属性をオーバーライドするか、デフォルトのテンプレートをオーバーライドすることで、フォームごとに変更できます。詳細については、 組み込みのフォームテンプレートをオーバーライドする も参照してください。
出力スタイル¶
フォームの出力スタイルを変更する推奨されるアプローチは、サイト全体、フォームごと、またはインスタンスごとにカスタムフォームテンプレートを設定することです。例については、 再利用可能なフォームテンプレート を参照してください。
以下のヘルパー関数は後方互換性のために提供され、特定の template_name
値を渡す Form.render()
へのプロキシです。
注釈
フレームワークが提供するテンプレートと出力スタイルのうち、デフォルトの as_div()
は as_p()
, as_table()
, as_ul()
バージョンよりも推奨されます。なぜなら、このテンプレートは <fieldset>
と <legend>
を実装しており、関連する入力をグループ化し、スクリーンリーダーユーザがナビゲートしやすいからです。
各ヘルパーは、適切なテンプレート名を指定する属性とフォームメソッドをペアにします。
as_div()
¶
- Form.template_name_div¶
as_div()
に使用されるテンプレート。デフォルト: 'django/forms/div.html'
。
- Form.as_div()¶
as_div()
はフォームを一連の <div>
要素としてレンダリングし、各 <div>
には以下のように一つのフィールドを含みます
>>> f = ContactForm()
>>> f.as_div()
… これは次のようなHTMLを生成します:
<div>
<label for="id_subject">Subject:</label>
<input type="text" name="subject" maxlength="100" required id="id_subject">
</div>
<div>
<label for="id_message">Message:</label>
<input type="text" name="message" required id="id_message">
</div>
<div>
<label for="id_sender">Sender:</label>
<input type="email" name="sender" required id="id_sender">
</div>
<div>
<label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself">
</div>
as_p()
¶
- Form.template_name_p¶
as_p()
に使われるテンプレート。デフォルト: 'django/forms/p.html'
。
- Form.as_p()¶
as_p()
は、フォームを一連の <p>
タグとしてレンダリングし、各 <p>
は1つのフィールドを含みます。
>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>'
>>> print(f.as_p())
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>
<p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>
as_ul()
¶
- Form.template_name_ul¶
as_ul()
によって使用されるテンプレート。デフォルト: 'django/forms/ul.html'
。
- Form.as_ul()¶
as_ul()
は、フォームを一連の <li>
タグとしてレンダリングし、各 <li>
には一つのフィールドが含まれます。柔軟性のために、<ul>
に任意のHTML属性を指定できるように、 <ul>
や </ul>
は含まれ ません 。
>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>
as_table()
¶
- Form.template_name_table¶
as_table()
によって使用されるテンプレート。デフォルト: 'django/forms/table.html'
。
- Form.as_table()¶
as_table()
はフォームを HTML の <table>
としてレンダリングします:
>>> f = ContactForm()
>>> f.as_table()
'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>'
>>> print(f.as_table())
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>
必須フォームとエラーのあるフォームのスタイリング¶
- Form.error_css_class¶
- Form.required_css_class¶
必須フォームやエラーのあるフォームの行を装飾するのはとても一般的です。たとえば、必須フォームの行は太字にしたり、エラーであれば赤色にしたくなることもあるでしょう。
Form
クラスには、必須フォームやエラーのあるフォームに class
属性を追加するためのいくつかのフックを用意しています。具体的には、 Form.error_css_class
属性や Form.required_css_class
属性をセットします:
from django import forms
class ContactForm(forms.Form):
error_css_class = "error"
required_css_class = "required"
# ... and the rest of your fields here
それを行ったら、必要に応じて行には "error"
および/または "required"
のクラスが与えられます。HTMLは以下のようになるでしょう:
>>> f = ContactForm(data)
>>> print(f)
<div class="required"><label for="id_subject" class="required">Subject:</label> ...
<div class="required"><label for="id_message" class="required">Message:</label> ...
<div class="required"><label for="id_sender" class="required">Sender:</label> ...
<div><label for="id_cc_myself">Cc myself:</label> ...
>>> f["subject"].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f["subject"].legend_tag()
<legend class="required" for="id_subject">Subject:</legend>
>>> f["subject"].label_tag(attrs={"class": "foo"})
<label for="id_subject" class="foo required">Subject:</label>
>>> f["subject"].legend_tag(attrs={"class": "foo"})
<legend for="id_subject" class="foo required">Subject:</legend>
You may further modify the rendering of form rows by using a custom BoundField.
フォームウィジェットのレンダリングを設定する¶
- Form.default_renderer¶
フォームの renderer を指定します。デフォルトは None
で、 FORM_RENDERER
設定で指定されたデフォルトのレンダラーを使用することを意味します。
これはクラスの属性としてフォーム定義の際に設定するもしくは、Form.__init__()
に renderer
引数を使うことで設定します。たとえば:
from django import forms
class MyForm(forms.Form):
default_renderer = MyRenderer()
もしくは:
form = MyForm(renderer=MyRenderer())
フィールドの順序に関する記述¶
as_p()
, as_ul()
, as_table()
ショートカットでは、フィールドはフォームクラスで定義した順序で表示されます。たとえば、 ContactForm
の例では、フィールドは subject
, message
, sender
, cc_myself
の順で定義されます。 HTML アウトプットの順序を変更するには、クラスの中で定義する順序を変えます。
順序のカスタマイズには、ほかにもいくつかの方法があります:
- Form.field_order¶
デフォルトでは Form.field_order=None
で、これはフォームクラスでフィールドを定義した順番を保持します。field_order
がフィールド名のリストである場合、指定されたリストに従ってフィールドが順序付けられ、残りのフィールドはデフォルトの順序に従って追加されます。リスト内の未知のフィールド名は無視されます。これにより、サブクラスでフィールドを None
に設定して無効にしても、順序を再定義する必要がなくなります。
Form
に Form.field_order
引数を使うことで、フィールドの順序をオーバーライドすることもできます。 Form
の中で field_order
が定義されていて、 かつ Form
をインスタンス化する際に field_order
をインクルードする場合、後者の field_order
が優先されます。
- Form.order_fields(field_order)¶
また、 order_fields()
に field_order
と同様のフィールド名のリストを用いて、いつでもフィールドの順序を変更できます。
エラーの表示方法¶
If you render a bound Form
object, the act of rendering will automatically
run the form's validation if it hasn't already happened, and the HTML output
will include the validation errors as a <ul class="errorlist">
.
The following:
>>> data = {
... "subject": "",
... "message": "Hi there",
... "sender": "invalid email address",
... "cc_myself": True,
... }
>>> ContactForm(data).as_div()
… これは次のようなHTMLを生成します:
<div>
<label for="id_subject">Subject:</label>
<ul class="errorlist" id="id_subject_error"><li>This field is required.</li></ul>
<input type="text" name="subject" maxlength="100" required aria-invalid="true" aria-describedby="id_subject_error" id="id_subject">
</div>
<div>
<label for="id_message">Message:</label>
<textarea name="message" cols="40" rows="10" required id="id_message">Hi there</textarea>
</div>
<div>
<label for="id_sender">Sender:</label>
<ul class="errorlist" id="id_sender_error"><li>Enter a valid email address.</li></ul>
<input type="email" name="sender" value="invalid email address" maxlength="320" required aria-invalid="true" aria-describedby="id_sender_error" id="id_sender">
</div>
<div>
<label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" checked>
</div>
Django's default form templates will associate validation errors with their
input by using the aria-describedby
HTML attribute when the field has an
auto_id
and a custom aria-describedby
is not provided. If a custom
aria-describedby
is set when defining the widget this will override the
default value.
If the widget is rendered in a <fieldset>
then aria-describedby
is
added to this element, otherwise it is added to the widget's HTML element (e.g.
<input>
).
aria-describedby
was added to associate errors with its input.
エラーリストのフォーマットをカスタムする¶
- class ErrorList(initlist=None, error_class=None, renderer=None, field_id=None)[ソース]¶
デフォルトでは、フォームはバリデーションエラーを整形するために
django.forms.utils.ErrorList
を使用します。ErrorList
はリストのようなオブジェクトであり、initlist
はエラーのリストです。さらに、このクラスは以下の属性とメソッドを持っています。Changed in Django 5.2:The
field_id
argument was added.- error_class¶
エラーリストをレンダリングする際に使用されるCSSクラス。指定されたクラスは、デフォルトの
errorlist
クラスに追加されます。
- renderer¶
ErrorList
に使用する レンダラー を指定します。デフォルトではNone
であり、これはFORM_RENDERER
設定で指定されたデフォルトのレンダラーを使用することを意味します。
- field_id¶
- New in Django 5.2.
An
id
for the field for which the errors relate. This allows an HTMLid
attribute to be added in the error template and is useful to associate the errors with the field. The default template uses the formatid="{{ field_id }}_error"
and a value is provided byForm.add_error()
using the field'sauto_id
.
- template_name¶
__str__
やrender()
を呼び出した際に使用されるテンプレートの名前です。デフォルトでは、これは'django/forms/errors/list/default.html'
であり、'ul.html'
テンプレートのプロキシとなります。
- template_name_text¶
as_text()
を呼び出す際に使用されるテンプレートの名前です。デフォルトでは、これは'django/forms/errors/list/text.html'
です。このテンプレートは、エラーを箇条書きのリストとしてレンダリングします。
- template_name_ul¶
as_ul()
を呼び出すときに使用されるテンプレートの名前です。デフォルトではこれは'django/forms/errors/list/ul.html'
です。このテンプレートは、error_class
で定義された CSS クラスを持つ包括的な<ul>
で<li>
タグ内のエラーをレンダリングします。
- get_context()[ソース]¶
テンプレート内のエラーのレンダリング用のコンテキストを返します。
利用可能なコンテキストは次のとおりです。
errors
: エラーのリスト。error_class
: CSSクラスの文字列。
- render(template_name=None, context=None, renderer=None)¶
renderメソッドは、
__str__
とas_ul()
メソッドの両方から呼び出されます。すべての引数はオプションで、デフォルト値は以下の通りです:
template_name
:template_name
が返す値context
:get_context()
が返す値renderer
:renderer
が返す値
- as_text()¶
エラーリストを
template_name_text
で定義されたテンプレートを使用してレンダリングします。
- as_ul()¶
template_name_ul
で定義されたテンプレートを使用してエラーリストをレンダリングします。
エラーのレンダリングをカスタマイズしたい場合は、
template_name
属性をオーバーライドするか、あるいはデフォルトテンプレートをオーバーライドすることによって達成できます。詳しくは 組み込みのフォームテンプレートをオーバーライドする も参照してください。
さらに詳細なアウトプット¶
as_p()
, as_ul()
, as_table()
メソッドはショートカットです -- フォームオブジェクトを表示する唯一の方法ではありません。
- class BoundField[ソース]¶
Form
インスタンスのひとつのフィールドを HTML として表示したり、その属性にアクセスするのに使います。このオブジェクトの
__str__()
メソッドは、このフィールドの HTML を表示します。You can use
Form.bound_field_class
andField.bound_field_class
to specify a differentBoundField
class per form or per field, respectively.See BoundField のカスタマイズ for examples of overriding a
BoundField
.
単一の BoundField
を取得するには、フィールド名をキーとしてフォームに対して辞書参照構文を使用します。
>>> form = ContactForm()
>>> print(form["subject"])
<input id="id_subject" type="text" name="subject" maxlength="100" required>
全ての BoundField
オブジェクトを取得するには、フォームをイテレートします:
>>> form = ContactForm()
>>> for boundfield in form:
... print(boundfield)
...
<input id="id_subject" type="text" name="subject" maxlength="100" required>
<input type="text" name="message" id="id_message" required>
<input type="email" name="sender" id="id_sender" required>
<input type="checkbox" name="cc_myself" id="id_cc_myself">
フィールド固有の出力は、フォームオブジェクトの auto_id
設定を反映します:
>>> f = ContactForm(auto_id=False)
>>> print(f["message"])
<input type="text" name="message" required>
>>> f = ContactForm(auto_id="id_%s")
>>> print(f["message"])
<input type="text" name="message" id="id_message" required>
BoundField
の属性一覧¶
- BoundField.aria_describedby[ソース]¶
- New in Django 5.2.
Returns an
aria-describedby
reference to associate a field with its help text and errors. ReturnsNone
ifaria-describedby
is set inWidget.attrs
to preserve the user defined attribute when rendering the form.
- BoundField.auto_id[ソース]¶
この
BoundField
の HTML ID 属性。Form.auto_id
がFalse
であれば、空の文字列を返します。
- BoundField.data[ソース]¶
このプロパティは、ウィジェットの
value_from_datadict()
メソッドによって抽出された、このBoundField
のデータを返します。もしデータが与えられていない場合は、None
を返します。>>> unbound_form = ContactForm() >>> print(unbound_form["subject"].data) None >>> bound_form = ContactForm(data={"subject": "My Subject"}) >>> print(bound_form["subject"].data) My Subject
- BoundField.errors[ソース]¶
プリント時に HTML の
<ul class="errorlist">
として表示される リストのようなオブジェクト です:>>> data = {"subject": "hi", "message": "", "sender": "", "cc_myself": ""} >>> f = ContactForm(data, auto_id=False) >>> print(f["message"]) <input type="text" name="message" required aria-invalid="true"> >>> f["message"].errors ['This field is required.'] >>> print(f["message"].errors) <ul class="errorlist"><li>This field is required.</li></ul> >>> f["subject"].errors [] >>> print(f["subject"].errors) >>> str(f["subject"].errors) ''
エラーを含むフィールドをレンダリングする際、そのフィールドのウィジェットに
aria-invalid="true"
が設定され、スクリーンリーダーユーザーにエラーが存在することを示します。
- BoundField.field¶
この
BoundField
がラップしているフォームクラスのField
インスタンス。
- BoundField.form¶
この
BoundField
がバインドされているForm
インスタンス。
- BoundField.id_for_label[ソース]¶
このプロパティを使用して、このフィールドのIDをレンダリングします。例えば、(
label_tag()
/legend_tag()
がこれを行ってくれるにも関わらず、) テンプレートで手動で<label>
を構築している場合は:<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}
デフォルトでは、これはフィールドの名前に
id_
を前につけたものになります(上の例では "id_my_field
")。フィールドのウィジェットのattrs
を設定することで、IDを変更できます。例えば、以下のようにフィールドを宣言します:my_field = forms.CharField(widget=forms.TextInput(attrs={"id": "myFIELD"}))
そして、上記のテンプレートを使用すると、以下のように表示されます:
<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required>
- BoundField.initial[ソース]¶
BoundField.initial
を使用して、フォームフィールドの初期データを取得します。データは、存在する場合はForm.initial
から、そうでなければField.initial
から取得されます。呼び出し可能オブジェクトの値は評価されます。より多くの例については、 フォームの初期値 を参照してください。BoundField.initial
はその返り値をキャッシュします。これは、返り値が変わる可能性がある呼び出し可能オブジェクト(例:datetime.now
やuuid.uuid4
など)を扱う際に特に便利です。>>> from datetime import datetime >>> class DatedCommentForm(CommentForm): ... created = forms.DateTimeField(initial=datetime.now) ... >>> f = DatedCommentForm() >>> f["created"].initial datetime.datetime(2021, 7, 27, 9, 5, 54) >>> f["created"].initial datetime.datetime(2021, 7, 27, 9, 5, 54)
get_initial_for_field()
よりもBoundField.initial
を使うことをお勧めします。
この
BoundField
のウィジェットが非表示の場合、True
を返します。
- BoundField.label¶
フィールドの
label
。これはlabel_tag()
/legend_tag()
で使用されます。
- BoundField.name¶
このフィールドのフォーム上での名前:
>>> f = ContactForm() >>> print(f["subject"].name) subject >>> print(f["message"].name) message
- BoundField.template_name[ソース]¶
BoundField.as_field_group()
でレンダリングされるテンプレートの名前。指定されていれば
template_name
の値を、そうでなければfield_template_name
の値を返すプロパティ。
BoundField
のメソッド¶
- BoundField.as_field_group()¶
フィールドを
BoundField.render()
を使用してデフォルト値でレンダリングし、設定されている場合はテンプレートのtemplate_name
、そうでなければfield_template_name
を使用して、BoundField
をラベル、ヘルプテキスト、エラーとともにレンダリングします。
これを
<input type="hidden">
として表現するためのHTMLの文字列を返します。**kwargs
はas_widget()
に渡されます。このメソッドは主に内部で使用されます。代わりにウィジェットを使用すべきです。
- BoundField.as_widget(widget=None, attrs=None, only_initial=False)[ソース]¶
渡されたウィジェットをレンダリングして、
attrs
として渡された任意のHTML属性を追加してフィールドをレンダリングします。ウィジェットが指定されていない場合、フィールドのデフォルトウィジェットが使用されます。only_initial
は Django の内部で使用されるものであり、明示的に設定すべきではありません。
- BoundField.css_classes(extra_classes=None)[ソース]¶
Djangoのレンダリングショートカットを利用すると、必須のフォームフィールドやエラーを含むフィールドを示すためのCSSクラスが使用されます。フォームを手動でレンダリングする場合は、
css_classes
メソッドを使用してこれらのCSSクラスにアクセスできます。>>> f = ContactForm(data={"message": ""}) >>> f["message"].css_classes() 'required'
エラークラスと必須クラスが必要な場合に加えて、追加のクラスを提供したい場合は、引数としてそのクラスを提供できます:
>>> f = ContactForm(data={"message": ""}) >>> f["message"].css_classes("foo bar") 'foo bar required'
- BoundField.get_context()[ソース]¶
レンダリングするためのテンプレートコンテキストを返します。利用可能なコンテキストは、バインドされたフィールドのインスタンスである
field
です。
- BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None)[ソース]¶
フォームフィールドのラベルタグを、
Form.template_name_label
で指定されたテンプレートを使用してレンダリングします。利用可能なコンテキストは次のとおりです。
field
: このBoundField
のインスタンス。contents
: デフォルトではBoundField.label
とForm.label_suffix
(または設定されている場合はField.label_suffix
) の結合された文字列です。これはcontents
とlabel_suffix
引数によって上書きできます。attrs
:for
、Form.required_css_class
、およびid
を含むdict
。id
はフィールドのウィジェットattrs
またはBoundField.auto_id
によって生成されます。追加の属性はattrs
引数によって提供できます。use_tag
: ラベルにid
がある場合はTrue
、そうでない場合はFalse
の真偽値です。False
の場合、デフォルトテンプレートはtag
を省略します。tag
: タグをカスタマイズするオプションの文字列で、デフォルトはlabel
です。
Tip
テンプレートでは、
field
はBoundField
のインスタンスです。したがって、field.field
でアクセスするBoundField.field
は、あなたが宣言したフィールド、例えばforms.CharField
になります。フォームフィールドのラベルタグを別々にレンダリングするには、その
label_tag()
メソッドを呼び出します:>>> f = ContactForm(data={"message": ""}) >>> print(f["message"].label_tag()) <label for="id_message">Message:</label>
レンダリングをカスタマイズしたい場合は、
Form.template_name_label
属性をオーバーライドするか、一般的にはデフォルトのテンプレートをオーバーライドしてください。詳細は、 組み込みのフォームテンプレートをオーバーライドする も参照してください。
- BoundField.legend_tag(contents=None, attrs=None, label_suffix=None)[ソース]¶
tag='legend'
を指定してlabel_tag()
を呼び出すと、ラベルを<legend>
タグでレンダリングします。これは、<label>
よりも<legend>
が適しているラジオボタンや複数のチェックボックスウィジェットをレンダリングする際に便利です。
- BoundField.render(template_name=None, context=None, renderer=None)¶
renderメソッドは
as_field_group
によって呼び出されます。すべての引数はオプションであり、デフォルト値は次のとおりです。template_name
:BoundField.template_name
context
:BoundField.get_context()
が返す値renderer
:Form.default_renderer
が返す値
template_name
を渡すことで、単一の呼び出しに使用されるテンプレートをカスタマイズできます。
- BoundField.value()[ソース]¶
このメソッドを使用すると、
Widget
によってレンダリングされるフィールドの生の値をレンダリングできます:>>> initial = {"subject": "welcome"} >>> unbound_form = ContactForm(initial=initial) >>> bound_form = ContactForm(data={"subject": "hi"}, initial=initial) >>> print(unbound_form["subject"].value()) welcome >>> print(bound_form["subject"].value()) hi
BoundField
のカスタマイズ¶
- Form.bound_field_class¶
Define a custom BoundField
class to use when rendering
the form. This takes precedence over the project-level
BaseRenderer.bound_field_class
(along with a custom
FORM_RENDERER
), but can be overridden by the field-level
Field.bound_field_class
.
If not defined as a class variable, bound_field_class
can be set via the
bound_field_class
argument in the Form
or Field
constructor.
For compatibility reasons, a custom form field can still override
Field.get_bound_field()
to use a custom class, though any of the
previous options are preferred.
You may want to use a custom BoundField
if you need to access some
additional information about a form field in a template and using a subclass of
Field
isn't sufficient.
For example, if you have a GPSCoordinatesField
, and want to be able to
access additional information about the coordinates in a template, this could
be implemented as follows:
class GPSCoordinatesBoundField(BoundField):
@property
def country(self):
"""
Return the country the coordinates lie in or None if it can't be
determined.
"""
value = self.value()
if value:
return get_country_from_coordinates(value)
else:
return None
class GPSCoordinatesField(Field):
bound_field_class = GPSCoordinatesBoundField
これで、テンプレート内で {{ form.coordinates.country }}
を使って国にアクセスできるようになりました。
You may also want to customize the default form field template rendering. For
example, you can override BoundField.label_tag()
to add a custom class:
class StyledLabelBoundField(BoundField):
def label_tag(self, contents=None, attrs=None, label_suffix=None, tag=None):
attrs = attrs or {}
attrs["class"] = "wide"
return super().label_tag(contents, attrs, label_suffix, tag)
class UserForm(forms.Form):
bound_field_class = StyledLabelBoundField
name = CharField()
This would update the default form rendering:
>>> f = UserForm()
>>> print(f["name"].label_tag)
<label for="id_name" class="wide">Name:</label>
To add a CSS class to the wrapping HTML element of all fields, a BoundField
can be overridden to return a different collection of CSS classes:
class WrappedBoundField(BoundField):
def css_classes(self, extra_classes=None):
parent_css_classes = super().css_classes(extra_classes)
return f"field-class {parent_css_classes}".strip()
class UserForm(forms.Form):
bound_field_class = WrappedBoundField
name = CharField()
This would update the form rendering as follows:
>>> f = UserForm()
>>> print(f)
<div class="field-class"><label for="id_name">Name:</label><input type="text" name="name" required id="id_name"></div>
Alternatively, to override the BoundField
class at the project level,
BaseRenderer.bound_field_class
can be defined on a custom
FORM_RENDERER
:
mysite/renderers.py
¶from django.forms.renderers import DjangoTemplates
from .forms import CustomBoundField
class CustomRenderer(DjangoTemplates):
bound_field_class = CustomBoundField
settings.py
¶FORM_RENDERER = "mysite.renderers.CustomRenderer"
アップロードされたファイルをフォームにバインドする¶
FileField
と ImageField
フィールドを持つフォームを扱うのは、通常のフォームよりも少し複雑です。
まず、ファイルをアップロードするには、<form>
要素が enctype
を "multipart/form-data"
として正しく定義していることを確認する必要があります:
<form enctype="multipart/form-data" method="post" action="/foo/">
次に、フォームを使用する際には、ファイルデータをバインドする必要があります。ファイルデータは通常のフォームデータとは別に扱われるため、フォームに FileField
や ImageField
が含まれている場合、フォームをバインドする際に第2引数を指定する必要があります。したがって、 ImageField
を mugshot
という名前で ContactForm に追加した場合、mugshot イメージを含むファイルデータをバインドする必要があります:
# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> data = {
... "subject": "hello",
... "message": "Hi there",
... "sender": "foo@example.com",
... "cc_myself": True,
... }
>>> file_data = {"mugshot": SimpleUploadedFile("face.jpg", b"file data")}
>>> f = ContactFormWithMugshot(data, file_data)
実際には、通常、(フォームデータのソースとして request.POST
を使用するのと同様に、)ファイルデータのソースとして request.FILES
を指定します:
# Bound form with an image field, data from the request
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
バインドされていないフォームを作成する方法は、いつも通りです。フォームデータ と ファイルデータの両方を省略します。
# Unbound form with an image field
>>> f = ContactFormWithMugshot()
マルチパートフォームのテスト¶
- Form.is_multipart()¶
再利用可能なビューやテンプレートを書いている場合、フォームがマルチパートフォームかどうかを事前に知ることができないかもしれません。 is_multipart()
メソッドは、フォームの送信にマルチパートエンコーディングが必要かどうかを教えてくれます:
>>> f = ContactFormWithMugshot()
>>> f.is_multipart()
True
テンプレートでの使い方の例です:
{% if form.is_multipart %}
<form enctype="multipart/form-data" method="post" action="/foo/">
{% else %}
<form method="post" action="/foo/">
{% endif %}
{{ form }}
</form>
フォームをサブクラス化する¶
複数の Form
クラスがフィールドを共有している場合、サブクラス化を利用して冗長性を排除できます。
カスタム Form
クラスをサブクラス化すると、親クラスのすべてのフィールドが含まれ、その後にサブクラスで定義したフィールドが続きます。
この例では、ContactFormWithPriority
は ContactForm
の全てのフィールドに加え、追加のフィールド priority
を含んでいます。ContactForm
のフィールドが最初に配置されます:
>>> class ContactFormWithPriority(ContactForm):
... priority = forms.CharField()
...
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div>
<div>Sender:<input type="email" name="sender" required></div>
<div>Cc myself:<input type="checkbox" name="cc_myself"></div>
<div>Priority:<input type="text" name="priority" required></div>
複数のフォームをサブクラス化し、フォームをミックスインとして扱うことができます。この例では、BeatleForm
が PersonForm
と InstrumentForm
(この順番で)の両方をサブクラス化し、そのフィールドリストは親クラスのフィールドを含んでいます:
>>> from django import forms
>>> class PersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
...
>>> class InstrumentForm(forms.Form):
... instrument = forms.CharField()
...
>>> class BeatleForm(InstrumentForm, PersonForm):
... haircut_type = forms.CharField()
...
>>> b = BeatleForm(auto_id=False)
>>> print(b)
<div>First name:<input type="text" name="first_name" required></div>
<div>Last name:<input type="text" name="last_name" required></div>
<div>Instrument:<input type="text" name="instrument" required></div>
<div>Haircut type:<input type="text" name="haircut_type" required></div>
親クラスから継承された Field
を、サブクラスでフィールドの名前を None
に設定することで、宣言的にフィールドを削除できます。たとえば次のようにします:
>>> from django import forms
>>> class ParentForm(forms.Form):
... name = forms.CharField()
... age = forms.IntegerField()
...
>>> class ChildForm(ParentForm):
... name = None
...
>>> list(ChildForm().fields)
['age']
フォームのプレフィックス¶
- Form.prefix¶
1 つの <form>
タグの中に複数の Django フォームを配置できます。各 Form
に独自の名前空間を与えるには、prefix
キーワード引数を使用します。
>>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father")
>>> print(mother)
<div><label for="id_mother-first_name">First name:</label><input type="text" name="mother-first_name" required id="id_mother-first_name"></div>
<div><label for="id_mother-last_name">Last name:</label><input type="text" name="mother-last_name" required id="id_mother-last_name"></div>
>>> print(father)
<div><label for="id_father-first_name">First name:</label><input type="text" name="father-first_name" required id="id_father-first_name"></div>
<div><label for="id_father-last_name">Last name:</label><input type="text" name="father-last_name" required id="id_father-last_name"></div>
プレフィックスは、フォームクラスにも指定できます:
>>> class PersonForm(forms.Form):
... ...
... prefix = "person"
...