Forms API —Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/ref/forms/api
移動先:案内検索

Forms API

このドキュメントについて

このドキュメントでは、Djangoのフォーム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()

相互依存するフィールドのカスタム検証を追加する必要がある場合は、Formclean()メソッドを実装します。 使用例については、相互に依存するフィールドのクリーニングと検証を参照してください。

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.errorsValidationErrorインスタンスを格納し、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のエラーがあるかどうかを指定するブール値を返します。 codeNoneの場合、フィールドにエラーが含まれていると、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()

フォームデータが初期データから変更されているかどうかを確認する必要がある場合は、Formhas_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'}

CharFieldEmailFieldなどのテキストベースのフィールドは、常に入力を文字列にクリーンアップすることに注意してください。 このドキュメントの後半で、エンコーディングへの影響について説明します。

データが検証しない場合、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_nameCharFieldであり、CharFieldであるため、nick_namecleaned_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>

フォーム要素のHTML id属性と<label>タグの構成

Form.auto_id

デフォルトでは、フォームのレンダリング方法は次のとおりです。

  • フォーム要素のHTML id属性。
  • ラベルの周りの対応する<label>タグ。 HTML <label>タグは、どのラベルテキストがどのフォーム要素に関連付けられているかを指定します。 この小さな機能強化により、フォームがより使いやすくなり、支援機器にとってよりアクセスしやすくなります。 <label>タグを使用することをお勧めします。

id属性値は、フォームフィールド名の前にid_を付けることによって生成されます。 ただし、id規則を変更したり、HTML id属性と<label>タグを完全に削除したりする場合は、この動作を構成できます。

Formコンストラクターのauto_id引数を使用して、idとラベルの動作を制御します。 この引数は、TrueFalse、または文字列である必要があります。

auto_idFalseの場合、フォーム出力には<label>タグもid属性も含まれません。

>>> f = ContactForm(auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" required></td></tr>
<tr><th>Sender:</th><td><input type="email" name="sender" required></td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself"></td></tr>
>>> 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>
>>> print(f.as_p())
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" required></p>
<p>Sender: <input type="email" name="sender" required></p>
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>

auto_idTrueに設定されている場合、フォーム出力には<label>タグが含まれ、フィールド名がidとして使用されます。フォームフィールドごとに:

>>> f = ContactForm(auto_id=True)
>>> print(f.as_table())
<tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" required></td></tr>
<tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" required></td></tr>
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself"></td></tr>
>>> print(f.as_ul())
<li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="message">Message:</label> <input type="text" name="message" id="message" required></li>
<li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></li>
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></li>
>>> print(f.as_p())
<p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="message">Message:</label> <input type="text" name="message" id="message" required></p>
<p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></p>
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></p>

auto_idがフォーマット文字'%s'を含む文字列に設定されている場合、フォーム出力には<label>タグが含まれ、id属性が生成されます。フォーマット文字列。 たとえば、フォーマット文字列'field_%s'の場合、subjectという名前のフィールドはid'field_subject'を取得します。 例を続ける:

>>> f = ContactForm(auto_id='id_for_%s')
>>> print(f.as_table())
<tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" required></td></tr>
<tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" required></td></tr>
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></td></tr>
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
>>> print(f.as_p())
<p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></p>
<p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></p>
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></p>

auto_id%sを含まない文字列など、他の真の値に設定されている場合、ライブラリはauto_idTrueであるかのように動作します。 ]。

デフォルトでは、auto_idは文字列'id_%s'に設定されています。

Form.label_suffix

フォームがレンダリングされるときにラベル名の後に追加される翻訳可能な文字列(デフォルトは英語のコロン(:))。

label_suffixパラメーターを使用して、その文字をカスタマイズしたり、完全に省略したりすることができます。

>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>

ラベルのサフィックスは、ラベルの最後の文字が句読文字でない場合にのみ追加されることに注意してください(英語では、.!?、または:)。

フィールドは、独自の label_suffix を定義することもできます。 これは、 Form.label_suffix よりも優先されます。 サフィックスは、 label_tag()label_suffixパラメーターを使用して、実行時にオーバーライドすることもできます。

Form.use_required_attribute

True(デフォルト)に設定すると、必須のフォームフィールドにrequired HTML属性が割り当てられます。

Formsets は、use_required_attribute=Falseを使用してフォームをインスタンス化し、フォームセットからフォームを追加および削除する際の誤ったブラウザー検証を回避します。


フォームのウィジェットのレンダリングを構成する

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の例では、フィールドはsubjectmessagesendercc_myselfの順序で定義されています。 HTML出力を並べ替えるには、これらのフィールドがクラスにリストされる順序を変更します。

順序をカスタマイズする方法は他にもいくつかあります。

Form.field_order

デフォルトでは、Form.field_order=Noneは、フォームクラスでフィールドを定義する順序を保持します。 field_orderがフィールド名のリストである場合、フィールドはリストで指定された順序で並べられ、残りのフィールドはデフォルトの順序に従って追加されます。 リスト内の不明なフィールド名は無視されます。 これにより、順序を再定義せずにNoneに設定することで、サブクラスのフィールドを無効にすることができます。

FormForm.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_idFalseの場合、空の文字列を返します。
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の文字列を返します。

**kwargsas_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/">

次に、フォームを使用するときは、ファイルデータをバインドする必要があります。 ファイルデータは通常のフォームデータとは別に処理されるため、フォームにFileFieldImageFieldが含まれている場合は、フォームをバインドするときに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>

フォームをミックスインとして扱い、複数のフォームをサブクラス化することができます。 この例では、BeatleFormPersonFormInstrumentFormの両方を(この順序で)サブクラス化し、そのフィールドリストには親クラスのフィールドが含まれています。

>>> 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'