Forms API
バインドされたフォームとバインドされていないフォーム
Form インスタンスは、データセットにバインドされているか、バインドされていないのいずれかです。
- データセットにバインドされている場合、そのデータを検証し、HTMLで表示されたデータを使用してフォームをHTMLとしてレンダリングできます。
- unbound の場合、検証を行うことはできませんが(検証するデータがないため)、空白のフォームをHTMLとしてレンダリングすることはできます。
- class Form
バインドされていない Form インスタンスを作成するには、クラスをインスタンス化します。
>>> f = ContactForm()
データをフォームにバインドするには、データを最初のパラメーターとして辞書として Form クラスコンストラクターに渡します。
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
この辞書では、キーはフィールド名であり、 Form クラスの属性に対応しています。 値は、検証しようとしているデータです。 これらは通常文字列になりますが、文字列である必要はありません。 渡すデータの種類は、フィールドによって異なります。これについては後で説明します。
- Form.is_bound
実行時にバインドされたフォームインスタンスとバインドされていないフォームインスタンスを区別する必要がある場合は、フォームの is_bound 属性の値を確認してください。
>>> f = ContactForm()
>>> f.is_bound
False
>>> f = ContactForm({'subject': 'hello'})
>>> f.is_bound
True
空のディクショナリを渡すと、空のデータを含む bound フォームが作成されることに注意してください。
>>> 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': '[email protected]',
... '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.']}
この辞書では、キーはフィールド名であり、値はエラーメッセージを表す文字列のリストです。 フィールドには複数のエラーメッセージが含まれる可能性があるため、エラーメッセージはリストに保存されます。
最初に is_valid()を呼び出さなくても、エラーにアクセスできます。 フォームのデータは、 is_valid()を初めて呼び出すか、エラーにアクセスしたときに検証されます。
エラーにアクセスした回数や is_valid()を呼び出した回数に関係なく、検証ルーチンは1回だけ呼び出されます。 これは、検証に副作用がある場合、それらの副作用は1回だけトリガーされることを意味します。
- 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()
メソッドの必要性は、下位互換性によるものです。 以前は、レンダリングされたエラーメッセージがForm.errors
ディクショナリに追加されるとすぐに、ValidationError
インスタンスが失われていました。 理想的には、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
のインスタンスにすることができます。 フォームエラーを定義する際のベストプラクティスについては、 Raising ValidationError を参照してください。
Form.add_error()
は、cleaned_data
から関連するフィールドを自動的に削除することに注意してください。
- Form.has_error(field, code=None)
このメソッドは、フィールドに特定のエラーcode
のエラーがあるかどうかを指定するブール値を返します。 code
がNone
の場合、フィールドにエラーが含まれていると、True
が返されます。
フィールド以外のエラーをチェックするには、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
フィールドに現在のセッションのユーザー名を入力したい場合があります。
これを実現するには、 Form に対して initial 引数を使用します。 この引数は、指定されている場合、フィールド名を初期値にマッピングする辞書である必要があります。 初期値を指定するフィールドのみを含めてください。 フォームにすべてのフィールドを含める必要はありません。 例えば:
>>> f = ContactForm(initial={'subject': 'Hi there!'})
これらの値は、バインドされていないフォームに対してのみ表示され、特定の値が指定されていない場合、フォールバック値として使用されません。
フィールドがイニシャル およびを定義する場合、Form
をインスタンス化するときにイニシャルを含め、後者は [ X141X]が優先されます。 この例では、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)
<tr><th>Name:</th><td><input type="text" name="name" value="instance" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>
- 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()
フォームデータが初期データから変更されているかどうかを確認する必要がある場合は、Form
でhas_changed()
メソッドを使用してください。
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data, initial=data)
>>> f.has_changed()
False
フォームが送信されると、フォームが再構築され、元のデータが提供されるため、比較を行うことができます。
>>> f = ContactForm(request.POST, initial=data)
>>> f.has_changed()
request.POST
のデータが initial またはFalse
で提供されたものと異なる場合、has_changed()
はTrue
になります。 結果は、フォームの各フィールドに対して 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>
Form インスタンスのフィールドを変更して、フォームでの表示方法を変更できます。
>>> f.as_table().split('\n')[0]
'<tr><th>Name:</th><td><input name="name" type="text" value="instance" required></td></tr>'
>>> f.fields['name'].label = "Username"
>>> f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="instance" required></td></tr>'
base_fields
属性を変更しないように注意してください。この変更は、同じPythonプロセス内の後続のすべてのContactForm
インスタンスに影響を与えるためです。
>>> f.base_fields['name'].label = "Username"
>>> another_f = CommentForm(auto_id=False)
>>> another_f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="class" required></td></tr>'
「クリーンな」データへのアクセス
- Form.cleaned_data
Form クラスの各フィールドは、データの検証だけでなく、データの「クリーンアップ」(一貫した形式への正規化)も行います。 これは、特定のフィールドのデータをさまざまな方法で入力できるため、常に一貫した出力が得られるため、優れた機能です。
たとえば、 DateField は、Python datetime.date
オブジェクトへの入力を正規化します。 '1994-07-15'
、datetime.date
オブジェクト、またはその他の多くの形式の文字列を渡すかどうかに関係なく、DateField
は常に [に正規化します。 X162X]オブジェクトが有効である限り。
データセットを使用して Form インスタンスを作成して検証すると、cleaned_data
属性を介してクリーンなデータにアクセスできます。
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': '[email protected]', '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'}
cleaned_data
は、Form
を定義するときに追加のデータを渡した場合でも、Form
で定義されたフィールドのキーを常にのみに含みます。 この例では、一連の追加フィールドをContactForm
コンストラクターに渡しますが、cleaned_data
にはフォームのフィールドのみが含まれています。
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... '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': '[email protected]', 'subject': 'hello'}
Form
が有効な場合、データに一部のオプションフィールドの値が含まれていなくても、cleaned_data
にはすべてのフィールドのキーと値が含まれます。 この例では、データディクショナリに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'}
上記の例では、nick_name
はCharField
であり、CharField
であるため、nick_name
のcleaned_data
値は空の文字列に設定されます。空の値を空の文字列として扱います。 各フィールドタイプは、その「空白」値が何であるかを認識しています。たとえば、DateField
の場合、空の文字列ではなくNone
になります。 この場合の各フィールドの動作の詳細については、以下の「組み込みField
クラス」セクションの各フィールドの「空の値」の注記を参照してください。
特定のフォームフィールド(名前に基づく)またはフォーム全体(さまざまなフィールドの組み合わせを考慮)の検証を実行するコードを記述できます。 これについての詳細は、フォームとフィールドの検証にあります。
フォームをHTMLとして出力する
Form
オブジェクトの2番目のタスクは、それ自体をHTMLとしてレンダリングすることです。 これを行うには、print
それ:
>>> f = ContactForm()
>>> print(f)
<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>
フォームがデータにバインドされている場合、HTML出力にはそのデータが適切に含まれます。 たとえば、フィールドが<input type="text">
で表されている場合、データはvalue
属性に含まれます。 フィールドが<input type="checkbox">
で表されている場合、そのHTMLには、必要に応じてchecked
が含まれます。
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="[email protected]" 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" checked></td></tr>
このデフォルトの出力は2列のHTMLテーブルで、各フィールドに<tr>
があります。 次の点に注意してください。
- 柔軟性のために、出力にはには
<table>
および</table>
タグが含まれず、<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>
タグは、ベストプラクティスに従うためにデフォルトで出力に含まれていますが、その動作は変更できます。 - 出力は、
<!DOCTYPE html>
をターゲットとするHTML5構文を使用します。 たとえば、checked='checked'
のXHTMLスタイルではなく、checked
などのブール属性を使用します。
フォームをprint
すると、<table>
出力がデフォルトの出力スタイルになりますが、他の出力スタイルも使用できます。 各スタイルはフォームオブジェクトのメソッドとして使用でき、各レンダリングメソッドは文字列を返します。
as_p()
- 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.as_ul()
as_ul()
は、フォームを一連の<li>
タグとしてレンダリングし、各<li>
には1つのフィールドが含まれます。 には<ul>
または</ul>
が含まれていないため、<ul>
で任意のHTML属性を指定して柔軟性を高めることができます。
>>> 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.as_table()
最後に、as_table()
はフォームをHTML <table>
として出力します。 これはprint
とまったく同じです。 実際、フォームオブジェクトをprint
すると、バックグラウンドでas_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)
<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 および/または[ X172X] 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.as_table())
<tr class="required"><th><label class="required" for="id_subject">Subject:</label> ...
<tr class="required"><th><label class="required" for="id_message">Message:</label> ...
<tr class="required error"><th><label class="required" for="id_sender">Sender:</label> ...
<tr><th><label for="id_cc_myself">Cc myself:<label> ...
>>> f['subject'].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f['subject'].label_tag(attrs={'class': 'foo'})
<label for="id_subject" class="foo required">Subject:</label>
フォームのウィジェットのレンダリングを構成する
- Form.default_renderer
フォームに使用するレンダラーを指定します。 デフォルトはNone
です。これは、:setting: `FORM_RENDERER` 設定で指定されたデフォルトのレンダラーを使用することを意味します。
フォームを宣言するときにこれをクラス属性として設定するか、renderer
引数をForm.__init__()
に使用できます。 例えば:
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
引数を使用して、フィールドの順序を上書きすることもできます。 フォームが field_order およびを定義する場合、Form
をインスタンス化するときにfield_order
を含め、後者は [X137X ]が優先されます。
- Form.order_fields(field_order)
field_order のように、フィールド名のリストとともにorder_fields()
を使用して、いつでもフィールドを再配置できます。
エラーの表示方法
バインドされたForm
オブジェクトをレンダリングする場合、レンダリングの動作により、フォームの検証がまだ行われていない場合は自動的に実行され、HTML出力には検証エラーが<ul class="errorlist">
の近くに含まれます。分野。 エラーメッセージの特定の位置は、使用している出力方法によって異なります。
>>> data = {'subject': '',
... 'message': 'Hi there',
... 'sender': 'invalid email address',
... 'cc_myself': True}
>>> f = ContactForm(data, auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" value="Hi there" required></td></tr>
<tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></td></tr>
<tr><th>Cc myself:</th><td><input checked type="checkbox" name="cc_myself"></td></tr>
>>> print(f.as_ul())
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <input type="text" name="message" value="Hi there" required></li>
<li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" required></li>
<li>Cc myself: <input checked type="checkbox" name="cc_myself"></li>
>>> print(f.as_p())
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" value="Hi there" required></p>
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
エラーリスト形式のカスタマイズ
デフォルトでは、フォームはdjango.forms.utils.ErrorList
を使用して検証エラーをフォーマットします。 エラーを表示するために代替クラスを使用したい場合は、構築時にそれを渡すことができます。
>>> from django.forms.utils import ErrorList
>>> class DivErrorList(ErrorList):
... def __str__(self):
... return self.as_divs()
... def as_divs(self):
... if not self: return ''
... return '<div class="errorlist">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self])
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
>>> f.as_p()
<div class="errorlist"><div class="error">This field is required.</div></div>
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" value="Hi there" required></p>
<div class="errorlist"><div class="error">Enter a valid email address.</div></div>
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
より詳細な出力
as_p()
、as_ul()
、およびas_table()
メソッドはショートカットであり、フォームオブジェクトを表示できる唯一の方法ではありません。
- class BoundField
Form インスタンスの単一フィールドのHTMLまたはアクセス属性を表示するために使用されます。
このオブジェクトの
__str__()
メソッドは、このフィールドのHTMLを表示します。
単一の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.auto_id
- この
BoundField
のHTMLID属性。 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> >>> 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) ''
- BoundField.field
- この BoundField がラップするフォームクラスのフォーム Field インスタンス。
- BoundField.form
- この BoundField がバインドされている Form インスタンス。
- BoundField.help_text
- フィールドの help_text 。
- BoundField.html_name
- ウィジェットのHTML
name
属性で使用される名前。 プレフィックスの形式が考慮されます。
- BoundField.id_for_label
このプロパティを使用して、このフィールドのIDをレンダリングします。 たとえば、テンプレートに
<label>
を手動で作成している場合( label_tag()がこれを行うにもかかわらず):<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.is_hidden
- この BoundField のウィジェットが非表示の場合、
True
を返します。
- BoundField.label
- フィールドのラベル。 これは label_tag()で使用されます。
- BoundField.name
次の形式のこのフィールドの名前:
>>> f = ContactForm() >>> print(f['subject'].name) subject >>> print(f['message'].name) message
- BoundField.widget_type
バージョン3.1の新機能。
末尾の
input
またはwidget
が削除された、ラップされたフィールドのウィジェットの小文字のクラス名を返します。 これは、レイアウトがウィジェットのタイプに依存するフォームを作成するときに使用できます。 例えば:{% for field in form %} {% if field.widget_type == 'checkbox' %} # render one way {% else %} # render another way {% endif %} {% endfor %}
BoundFieldの方法
- BoundField.as_hidden(attrs=None, **kwargs)
これを
<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.label_tag(contents=None, attrs=None, label_suffix=None)
フォームフィールドのラベルタグを個別にレンダリングするには、その
label_tag()
メソッドを呼び出すことができます。>>> f = ContactForm(data={'message': ''}) >>> print(f['message'].label_tag()) <label for="id_message">Message:</label>
自動生成されたラベルタグを置き換える
contents
パラメーターを指定できます。attrs
ディクショナリには、<label>
タグの追加属性が含まれる場合があります。生成されるHTMLには、フォームの label_suffix (デフォルトではコロン)、または設定されている場合は現在のフィールドの label_suffix が含まれます。 オプションの
label_suffix
パラメータを使用すると、以前に設定したサフィックスを上書きできます。 たとえば、空の文字列を使用して、選択したフィールドのラベルを非表示にすることができます。 テンプレートでこれを行う必要がある場合は、label_tag
にパラメーターを渡すことができるカスタムフィルターを作成できます。
- 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のカスタマイズ
テンプレートのフォームフィールドに関する追加情報にアクセスする必要があり、 Field のサブクラスを使用するだけでは不十分な場合は、 BoundField のカスタマイズも検討してください。
カスタムフォームフィールドはget_bound_field()
を上書きできます。
- Field.get_bound_field(form, field_name)
- Form のインスタンスとフィールドの名前を取得します。 戻り値は、テンプレートのフィールドにアクセスするときに使用されます。 ほとんどの場合、 BoundField のサブクラスのインスタンスになります。
たとえば、GPSCoordinatesField
があり、テンプレート内の座標に関する追加情報にアクセスできるようにしたい場合、これは次のように実装できます。
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):
def get_bound_field(self, form, field_name):
return GPSCoordinatesBoundField(form, self, field_name)
これで、テンプレート:Form.coordinates.country
を使用してテンプレートで国にアクセスできます。
アップロードされたファイルをフォームにバインドする
FileField
およびImageField
フィールドを持つフォームの処理は、通常のフォームよりも少し複雑です。
まず、ファイルをアップロードするには、<form>
要素がenctype
を"multipart/form-data"
として正しく定義していることを確認する必要があります。
<form enctype="multipart/form-data" method="post" action="/foo/">
次に、フォームを使用するときは、ファイルデータをバインドする必要があります。 ファイルデータは通常のフォームデータとは別に処理されるため、フォームにFileField
とImageField
が含まれている場合は、フォームをバインドするときに2番目の引数を指定する必要があります。 したがって、ContactFormを拡張してmugshot
というImageField
を含める場合は、マグショット画像を含むファイルデータをバインドする必要があります。
# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
>>> f = ContactFormWithMugshot(data, file_data)
実際には、通常、ファイルデータのソースとしてrequest.FILES
を指定します(フォームデータのソースとしてrequest.POST
を使用するのと同じように)。
# 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.as_ul())
<li>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <input type="text" name="message" required></li>
<li>Sender: <input type="email" name="sender" required></li>
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
<li>Priority: <input type="text" name="priority" required></li>
フォームをミックスインとして扱い、複数のフォームをサブクラス化することができます。 この例では、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.as_ul())
<li>First name: <input type="text" name="first_name" required></li>
<li>Last name: <input type="text" name="last_name" required></li>
<li>Instrument: <input type="text" name="instrument" required></li>
<li>Haircut type: <input type="text" name="haircut_type" required></li>
サブクラスでフィールドの名前をNone
に設定することにより、親クラスから継承されたField
を宣言的に削除することができます。 例えば:
>>> 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.as_ul())
<li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" required></li>
<li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" required></li>
>>> print(father.as_ul())
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" required></li>
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" required></li>
プレフィックスは、フォームクラスでも指定できます。
>>> class PersonForm(forms.Form):
... ...
... prefix = 'person'