Django5.1(131)—— 表单 API二(API参考)
表单 API二
将表单输出为 HTML
一个 Form
对象的第二个任务是将自己呈现为 HTML。要做到这一点,只需将它打印出来:
>>> 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
而不是 XHTML 风格的checked='checked'
。
虽然 <div>
输出是在打印表单时的默认输出样式,但你可以通过使用自己的表单模板来自定义输出,这可以在整个站点范围、每个表单或每个实例中进行设置。
默认渲染
当你打印一个表单时,默认的渲染使用以下方法和属性。
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_namecontext
:由 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
用于渲染字段的 <label>
的模板,当调用 BoundField.label_tag()/legend_tag() 时使用。可以通过覆盖此属性来更改每个表单的模板,也可以通过覆盖默认模板来更一般地更改,
输出样式
更改表单输出样式的推荐方法是设置自定义表单模板,可以是整个站点范围、每个表单或每个实例。有关示例,
以下的辅助函数是为了向后兼容而提供的,它们是对 Form.render() 的代理,传递了特定的 template_name
值。
备注
在框架提供的模板和输出样式中,推荐使用默认的 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>
包含一个字段:
>>> 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>
或 </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.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)
<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>
设置表单元素的 HTML id
属性和 <label>
标签。
Form.auto_id
默认情况下,表单渲染方法包括:
- 表单元素的 HTML
id
属性。 - 标签周围对应的
<label>
标签。HTML<label>
标签指定了哪个标签文本与哪个表单元素相关联。这个小小的改进使表单更加可用,也更容易被辅助设备访问。使用<label>
标签总是一个好主意。
id
属性值是通过将 id_
预置到表单字段名后生成的。 如果你想改变 id
惯例或完全删除 HTML id
属性和 <label>
标签,这种行为是可以设置的。
使用 Form
构造函数的 auto_id
参数来控制 id
和标签行为。这个参数必须是 True
、False
或一个字符串。
如果 auto_id
是 False
,那么表单输出将不包含 <label>
标签和 id
属性:
>>> f = ContactForm(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>
如果 auto_id
设置为 True
,那么表单输出将包含 <label>
标签,并且将使用字段名作为每个表单字段的 id
:
>>> f = ContactForm(auto_id=True)
>>> print(f)
<div><label for="subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="subject"></div>
<div><label for="message">Message:</label><textarea name="message" cols="40" rows="10" required id="message"></textarea></div>
<div><label for="sender">Sender:</label><input type="email" name="sender" required id="sender"></div>
<div><label for="cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="cc_myself"></div>
如果 auto_id
设置为包含格式字符 '%s'
的字符串,那么表单输出将包含 <label>
标签,并且将根据格式字符串生成 id
属性。例如,对于格式字符串 'field_%s'
,名为 subject
的字段将获得 id
值 'field_subject'
。继续我们的例子:
>>> f = ContactForm(auto_id="id_for_%s")
>>> print(f)
<div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message:</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender:</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
如果 auto_id
被设置为任何其他的真值——比如一个不包含 %s
的字符串——那么该库就会像 auto_id
是 True
一样。
默认情况下,auto_id
被设置为字符串 'id_%s'
。
Form.label_suffix
一个可翻译的字符串(英文默认为冒号(:
)),将在渲染表格时附加在任何标签名称之后。
可以使用 label_suffix
参数自定义该字符,或完全省略它:
>>> f = ContactForm(auto_id="id_for_%s", label_suffix="")
>>> print(f)
<div><label for="id_for_subject">Subject</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
>>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->")
>>> print(f)
<div><label for="id_for_subject">Subject -></label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message -></label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender -></label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself -></label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
请注意,只有当标签的最后一个字符不是标点符号时,才会加上标签后缀(在英文中,这些字符是 .、!、? 或 :)。
字段还可以定义自己的 label_suffix。这将优先于 Form.label_suffix。后缀也可以在运行时使用 label_suffix 参数来覆盖 label_tag()/ legend_tag()。
Form.use_required_attribute
当设置为 True
(默认)时,必填表单字段将有 required
HTML 属性。
表单集 实例化表单时使用 use_required_attribute=False 以避免从表单集中添加和删除表单时浏览器验证错误。
设置表单组件的渲染方式
Form.default_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。
如何显示错误
如果渲染一个已绑定的 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)
<div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required aria-invalid="true">
</div>
<div>Message:<textarea name="message" cols="40" rows="10" required>Hi there</textarea>
</div>
<div>Sender:<ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required aria-invalid="true">
</div>
<div>Cc myself:<input type="checkbox" name="cc_myself" checked>
</div>
自定义错误列表格式
class ErrorList
(initlist=None, error_class=None, renderer=None)[源代码]
默认情况下,表单使用 django.forms.utils.ErrorList
来格式化验证错误。ErrorList
是一个类似列表的对象,其中 initlist
是错误列表。此外,这个类有以下属性和方法。
-
error_class
渲染错误列表时要使用的 CSS 类。任何提供的类将被添加到默认的
errorlist
类中。 -
renderer
指定 渲染器 用于
ErrorList
。默认为None
,即使用由FORM_RENDER
配置指定的默认渲染器。 -
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'。这个模板在 <li> 标签中渲染错误,并使用 error_class 所定义的 CSS 类来包装
<ul>
。 -
get_context
()[源代码]返回模板中渲染错误的上下文。
可用的上下文:
errors
: 一个错误列表。error_class
:一个 CSS 类的字符串。
-
render
(template_name=None, context=None, renderer=None)渲染方法被
__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。
要检索单个 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
的 HTML ID 属性。如果 Form.auto_id 是 False
,则返回一个空字符串。
BoundField.data
[源代码]
该属性返回由 widget 的 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"
,以向屏幕阅读器用户指示存在错误。
Changed in Django 5.0:
当字段存在错误时,将添加 aria-invalid="true"
。
BoundField.field
这个 Field 封装的表单类中的表单 BoundField 实例。
BoundField.form
这个 Form 实例与这个 BoundField 绑定。
BoundField.help_text
字段的 help_text。
BoundField.html_name
部件的 HTML name
属性中使用的名称。它考虑到了 prefix 的形式。
BoundField.id_for_label
[源代码]
使用这个属性来渲染该字段的 ID。例如,如果你在模板中手动构造一个 <label>
(尽管 label_tag()/legend_tag() 会为你执行此操作):
<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}
默认情况下,这将是字段的名称,前缀为 id_ (上面的例子为 “id_my_field“)。你可以通过设置 attrs 对字段的部件进行修改。例如,声明一个字段是这样的:
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)
建议使用 BoundField.initial 而不是 get_initial_for_field()。
BoundField.is_hidden
[源代码]
如果这个 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
[源代码]
New in Django 5.0.
使用 BoundField.as_field_group() 渲染的模板的名称。
如果设置了 template_name,则返回该值,否则返回 field_template_name 的值的属性。
BoundField.use_fieldset
[源代码]
返回该 BoundField widget 的 use_fieldset
属性的值。
BoundField.widget_type
[源代码]
返回封装字段 widget 的类名的小写形式,去除任何尾随的 input
或 widget
。这可以在构建依赖于 widget 类型的表单时使用。例如:
{% for field in form %}{% if field.widget_type == 'checkbox' %}# render one way{% else %}# render another way{% endif %}
{% endfor %}
BoundField
方法
BoundField.as_field_group
()
New in Django 5.0.
使用默认值使用 BoundField.render() 渲染字段,渲染 BoundField,包括其标签、帮助文本和错误,使用模板的 template_name (如果设置)或者使用 field_template_name。
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.get_context
()[源代码]
New in Django 5.0.
返回用于渲染字段的模板上下文。可用的上下文是 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
,默认模板将省略tag
。tag
: 可选的字符串,用于自定义标签,默认为label
。
小技巧
在你的模板中 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>
标签呈现标签。这在呈现单选按钮和多选框小部件时非常有用,其中 <legend>
可能比 <label>
更合适。
BoundField.render
(template_name=None, context=None, renderer=None)
New in Django 5.0.
渲染方法由 as_field_group
调用。所有参数都是可选的,并且默认为:
template_name
: BoundField.template_namecontext
:由 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
如果你需要访问模板中表单字段的一些附加信息,而使用 Field 的子类还不够,也可以考虑自定义 BoundField。
自定义表单字段可以覆盖 get_bound_field()
。
Field.get_bound_field
(form, field_name)[源代码]
取一个Form 的实例和字段名。当在模板中访问该字段时,将使用返回值。它很可能是 BoundField 的一个子类的实例。
例如,如果你有一个 GPSCoordinatesField
,并希望能够在模板中访问关于坐标的附加信息,可以按以下方式实现:
class GPSCoordinatesBoundField(BoundField):@propertydef country(self):"""Return the country the coordinates lie in or None if it can't bedetermined."""value = self.value()if value:return get_country_from_coordinates(value)else:return Noneclass 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
时,你需要在绑定表单时指定第二个参数。因此,如果我们扩展我们的 ContactForm 以包括一个名为 mugshot
的 ImageField
,我们需要绑定包含头像图片的文件数据:
# 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.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)
<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
你可以将多个 Django 表单放在同一个 <form>
标签内。为每个 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"
...