“Django/docs/3.1.x/ref/forms/widgets”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:小部件 — Django 文档}} | ||
<div id="module-django.forms.widgets" class="section"> | <div id="module-django.forms.widgets" class="section"> | ||
<span id="widgets"></span> | <span id="widgets"></span> | ||
− | = | + | = 小工具 = |
− | + | 小部件是 Django 对 HTML 输入元素的表示。 小部件处理 HTML 的呈现,以及从对应于小部件的 GET/POST 字典中提取数据。 | |
− | |||
− | |||
− | + | 内置小部件生成的 HTML 使用 HTML5 语法,针对 <code><!DOCTYPE html></code>。 例如,它使用 <code>checked</code> 等布尔属性,而不是 <code>checked='checked'</code> 的 XHTML 样式。 | |
− | <code><!DOCTYPE html></code> | ||
− | |||
<div class="admonition tip"> | <div class="admonition tip"> | ||
− | + | 提示 | |
− | + | 小部件不应与 [[../fields|表单字段]] 混淆。 表单字段处理输入验证的逻辑并直接在模板中使用。 小部件处理网页上 HTML 表单输入元素的呈现和原始提交数据的提取。 但是,小部件确实需要 [[#widget-to-field|assigned]] 来形成字段。 | |
− | |||
− | |||
− | |||
− | |||
第27行: | 第20行: | ||
<span id="widget-to-field"></span> | <span id="widget-to-field"></span> | ||
− | == | + | == 指定小部件 == |
− | + | 每当您在表单上指定字段时,Django 将使用适合要显示的数据类型的默认小部件。 要查找哪个小部件用于哪个字段,请参阅有关 [[../fields#built-in-fields|内置字段类]] 的文档。 | |
− | |||
− | |||
− | [[../fields#built-in-fields| | ||
− | + | 但是,如果您想对字段使用不同的小部件,则可以在字段定义中使用 [[../fields#django.forms.Field|widget]] 参数。 例如: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第41行: | 第30行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django import forms |
class CommentForm(forms.Form): | class CommentForm(forms.Form): | ||
name = forms.CharField() | name = forms.CharField() | ||
url = forms.URLField() | url = forms.URLField() | ||
− | comment = forms.CharField(widget=forms.Textarea)</ | + | comment = forms.CharField(widget=forms.Textarea)</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 这将指定一个带有注释的表单,该表单使用更大的 [[#django.forms.Textarea|Textarea]] 小部件,而不是默认的 [[#django.forms.TextInput|TextInput]] 小部件。 | |
− | |||
第58行: | 第46行: | ||
<div id="setting-arguments-for-widgets" class="section"> | <div id="setting-arguments-for-widgets" class="section"> | ||
− | == | + | == 为小部件设置参数 == |
− | + | 许多小部件都有可选的额外参数; 它们可以在定义字段上的小部件时设置。 在以下示例中,为 [[#django.forms.SelectDateWidget|SelectDateWidget]] 设置了 [[#django.forms.SelectDateWidget.years|years]] 属性: | |
− | |||
− | [[#django.forms.SelectDateWidget | ||
− | [[#django.forms.SelectDateWidget| | ||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第69行: | 第54行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django import forms |
BIRTH_YEAR_CHOICES = ['1980', '1981', '1982'] | BIRTH_YEAR_CHOICES = ['1980', '1981', '1982'] | ||
第84行: | 第69行: | ||
widget=forms.CheckboxSelectMultiple, | widget=forms.CheckboxSelectMultiple, | ||
choices=FAVORITE_COLORS_CHOICES, | choices=FAVORITE_COLORS_CHOICES, | ||
− | )</ | + | )</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 有关哪些小部件可用以及它们接受哪些参数的更多信息,请参阅 [[#built-in-widgets|内置小部件]] 。 | |
− | |||
第96行: | 第80行: | ||
<div id="widgets-inheriting-from-the-select-widget" class="section"> | <div id="widgets-inheriting-from-the-select-widget" class="section"> | ||
− | == | + | == 继承自 Select 小部件的小部件 == |
− | + | 继承自 [[#django.forms.Select|Select]] 小部件的小部件处理选择。 它们为用户提供了一个可供选择的选项列表。 不同的小部件以不同的方式呈现此选择; [[#django.forms.Select|Select]] 小部件本身使用 <code><select></code> HTML 列表表示,而 [[#django.forms.RadioSelect|RadioSelect]] 使用单选按钮。 | |
− | |||
− | |||
− | <code><select></code> HTML | ||
− | |||
− | [[#django.forms.Select| | + | [[#django.forms.Select|Select]] 小部件默认用于 [[../fields#django.forms|ChoiceField]] 字段。 小部件上显示的选项继承自 [[../fields#django.forms|ChoiceField]],更改 [[../fields#django.forms.ChoiceField|ChoiceField.choices]] 将更新 [[#django.forms.Select.choices|Select.choices]]。 例如: |
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第113行: | 第90行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> from django import forms |
− | + | >>> CHOICES = [('1', 'First'), ('2', 'Second')] | |
− | + | >>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES) | |
− | + | >>> choice_field.choices | |
[('1', 'First'), ('2', 'Second')] | [('1', 'First'), ('2', 'Second')] | ||
− | + | >>> choice_field.widget.choices | |
[('1', 'First'), ('2', 'Second')] | [('1', 'First'), ('2', 'Second')] | ||
− | + | >>> choice_field.widget.choices = [] | |
− | + | >>> choice_field.choices = [('1', 'First and only')] | |
− | + | >>> choice_field.widget.choices | |
− | [('1', 'First and only')]</ | + | [('1', 'First and only')]</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 然而,提供 [[#django.forms.Select.choices|choices]] 属性的小部件可以与不基于选择的字段一起使用 - 例如 [[../fields#django.forms|CharField]] - 但建议使用 [[../fields#django.forms|ChoiceField]] -based field when the choices are inherent to the model and not just the representational widget. | |
− | |||
− | |||
− | choices are inherent to the model and not just the representational widget. | ||
第137行: | 第111行: | ||
<div id="customizing-widget-instances" class="section"> | <div id="customizing-widget-instances" class="section"> | ||
− | == | + | == 自定义小部件实例 == |
− | + | 当 Django 将小部件呈现为 HTML 时,它只会呈现非常少的标记——Django 不会添加类名或任何其他特定于小部件的属性。 这意味着,例如,所有 [[#django.forms.TextInput|TextInput]] 小部件在您的网页上将显示相同。 | |
− | |||
− | |||
− | |||
− | + | 自定义小部件有两种方式:[[#styling-widget-instances|每个小部件实例]]和[[#styling-widget-classes|每个小部件类]]。 | |
<div id="styling-widget-instances" class="section"> | <div id="styling-widget-instances" class="section"> | ||
<span id="id1"></span> | <span id="id1"></span> | ||
− | === | + | === 样式小部件实例 === |
− | + | 如果您想让一个小部件实例看起来与另一个不同,您需要在小部件对象实例化并分配给表单字段时指定其他属性(并且可能向您的 CSS 文件添加一些规则)。 | |
− | |||
− | |||
− | CSS | ||
− | + | 例如,采用以下形式: | |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第162行: | 第130行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django import forms |
class CommentForm(forms.Form): | class CommentForm(forms.Form): | ||
name = forms.CharField() | name = forms.CharField() | ||
url = forms.URLField() | url = forms.URLField() | ||
− | comment = forms.CharField()</ | + | comment = forms.CharField()</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 此表单将包含三个默认的 [[#django.forms.TextInput|TextInput]] 小部件,具有默认呈现 - 没有 CSS 类,没有额外的属性。 这意味着为每个小部件提供的输入框将呈现完全相同: | |
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第180行: | 第146行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> f = CommentForm(auto_id=False) |
− | + | >>> f.as_table() | |
− | + | <tr><th>Name:</th><td><input type="text" name="name" 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></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | + | 在真实的 Web 页面上,您可能不希望每个小部件看起来都一样。 您可能需要更大的评论输入元素,并且您可能希望“名称”小部件具有一些特殊的 CSS 类。 还可以指定 'type' 属性以利用新的 HTML5 输入类型。 为此,您在创建小部件时使用 [[#django.forms.Widget.attrs|Widget.attrs]] 参数: | |
− | |||
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第199行: | 第161行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">class CommentForm(forms.Form): |
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'})) | name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'})) | ||
url = forms.URLField() | url = forms.URLField() | ||
− | comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))</ | + | comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 您还可以修改表单定义中的小部件: | |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第213行: | 第175行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">class CommentForm(forms.Form): |
name = forms.CharField() | name = forms.CharField() | ||
url = forms.URLField() | url = forms.URLField() | ||
第219行: | 第181行: | ||
name.widget.attrs.update({'class': 'special'}) | name.widget.attrs.update({'class': 'special'}) | ||
− | comment.widget.attrs.update(size='40')</ | + | comment.widget.attrs.update(size='40')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 或者,如果该字段未直接在表单上声明(例如模型表单字段),则可以使用 [[../api#django.forms.Form|Form.fields]] 属性: | |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
第231行: | 第192行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">class CommentForm(forms.ModelForm): |
def __init__(self, *args, **kwargs): | def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | super().__init__(*args, **kwargs) | ||
self.fields['name'].widget.attrs.update({'class': 'special'}) | self.fields['name'].widget.attrs.update({'class': 'special'}) | ||
− | self.fields['comment'].widget.attrs.update(size='40')</ | + | self.fields['comment'].widget.attrs.update(size='40')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | Django | + | 然后 Django 将在呈现的输出中包含额外的属性: |
<div class="doctest highlight-default notranslate"> | <div class="doctest highlight-default notranslate"> | ||
第246行: | 第207行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> f = CommentForm(auto_id=False) |
− | + | >>> f.as_table() | |
− | + | <tr><th>Name:</th><td><input type="text" name="name" class="special" 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" size="40" required></td></tr></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | + | 您还可以使用 [[#django.forms.Widget.attrs|attrs]] 设置 HTML <code>id</code>。 有关示例,请参阅 [[../api#django.forms.BoundField|BoundField.id_for_label]]。 | |
− | [[../api#django.forms.BoundField| | ||
第263行: | 第223行: | ||
<span id="id2"></span> | <span id="id2"></span> | ||
− | === | + | === 样式小部件类 === |
− | + | 使用小部件,可以添加资产(<code>css</code> 和 <code>javascript</code>)并更深入地自定义它们的外观和行为。 | |
− | |||
− | + | 简而言之,您需要对小部件进行子类化,并 [[../../../topics/forms/media#assets-as-a-static-definition|定义“媒体”内部类]] 或 [[../../../topics/forms/media#dynamic-property|创建“媒体”属性]] 。 | |
− | [[../../../topics/forms/media#assets-as-a-static-definition| | ||
− | [[../../../topics/forms/media#dynamic-property| | ||
− | + | 这些方法涉及一些高级 Python 编程,并在 [[../../../topics/forms/media|Form Assets]] 主题指南中进行了详细描述。 | |
− | |||
第282行: | 第238行: | ||
<span id="id3"></span> | <span id="id3"></span> | ||
− | == | + | == 基本小部件类 == |
− | + | 基本小部件类 [[#django.forms.Widget|Widget]] 和 [[#django.forms.MultiWidget|MultiWidget]] 是所有 [[#built-in-widgets|内置小部件]] 的子类,可以作为自定义小部件的基础。 | |
− | |||
− | |||
<div id="widget" class="section"> | <div id="widget" class="section"> | ||
− | === | + | === Widget === |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">Widget</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">attrs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>这个抽象类不能被渲染,但提供了基本属性 [[#django.forms.Widget.attrs|attrs]]。 您还可以在自定义小部件上实现或覆盖 [[#django.forms.Widget.render|render()]] 方法。</p> |
− | [[#django.forms.Widget.attrs| | ||
− | [[#django.forms.Widget.render| | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">attrs</span></span></dt> |
− | <dd><p> | + | <dd><p>包含要在呈现的小部件上设置的 HTML 属性的字典。</p> |
− | |||
<div class="highlight-pycon notranslate"> | <div class="highlight-pycon notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="pycon">>>> from django import forms |
− | + | >>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name'}) | |
− | + | >>> name.render('name', 'A name') | |
− | ' | + | '<input title="Your name" type="text" name="name" value="A name" size="10">'</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>如果您为属性分配 <code>True</code> 或 <code>False</code> 的值,它将呈现为 HTML5 布尔属性:</p> |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> name = forms.TextInput(attrs={'required': True}) |
− | + | >>> name.render('name', 'A name') | |
− | ' | + | '<input name="name" type="text" value="A name" required>' |
− | + | >>> | |
− | + | >>> name = forms.TextInput(attrs={'required': False}) | |
− | + | >>> name.render('name', 'A name') | |
− | ' | + | '<input name="name" type="text" value="A name">'</syntaxhighlight> |
</div> | </div> | ||
第332行: | 第282行: | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">supports_microseconds</span></span></dt> |
− | <dd><p> | + | <dd><p>默认为 <code>True</code> 的属性。 如果设置为 <code>False</code>,<code>datetime</code> 和 <code>time</code> 值的微秒部分将设置为 <code>0</code>。</p></dd></dl> |
− | |||
− | <code>time</code> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">format_value</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">value</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>清理并返回一个值以在小部件模板中使用。 <code>value</code> 不能保证是有效的输入,因此子类实现应该防御性地编程。</p></dd></dl> |
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">get_context</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">value</span></span>'', ''<span class="n"><span class="pre">attrs</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>返回呈现小部件模板时要使用的值字典。 默认情况下,字典包含一个键,<code>'widget'</code>,它是包含以下键的小部件的字典表示:</p> |
− | |||
− | <code>'widget'</code> | ||
− | |||
<ul> | <ul> | ||
− | <li><p><code>'name'</code> | + | <li><p><code>'name'</code>:来自 <code>name</code> 参数的字段名称。</p></li> |
− | <li><p><code>'is_hidden'</code> | + | <li><p><code>'is_hidden'</code>:指示此小部件是否隐藏的布尔值。</p></li> |
− | + | <li><p><code>'required'</code>:一个布尔值,指示是否需要此小部件的字段。</p></li> | |
− | <li><p><code>'required'</code> | + | <li><p><code>'value'</code>:[[#django.forms.Widget.format_value|format_value()]] 返回的值。</p></li> |
− | + | <li><p><code>'attrs'</code>:要在呈现的小部件上设置的 HTML 属性。 [[#django.forms.Widget.attrs|attrs]] 属性和 <code>attrs</code> 参数的组合。</p></li> | |
− | <li><p><code>'value'</code> | + | <li><p><code>'template_name'</code>:<code>self.template_name</code> 的值。</p></li></ul> |
− | <li><p><code>'attrs'</code> | ||
− | |||
− | <li><p><code>'template_name'</code> | ||
− | <p><code>Widget</code> | + | <p><code>Widget</code> 子类可以通过覆盖此方法提供自定义上下文值。</p></dd></dl> |
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">id_for_label</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">id_</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>给定字段的 ID,返回此小部件的 HTML ID 属性以供 <code><label></code> 使用。 如果 ID 不可用,则返回 <code>None</code>。</p> |
− | + | <p>这个钩子是必要的,因为一些小部件有多个 HTML 元素,因此有多个 ID。 在这种情况下,此方法应返回与小部件标签中的第一个 ID 对应的 ID 值。</p></dd></dl> | |
− | <p> | ||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">render</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">value</span></span>'', ''<span class="n"><span class="pre">attrs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">renderer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>使用给定的渲染器将小部件渲染为 HTML。 如果 <code>renderer</code> 是 <code>None</code>,则使用 [[#id4|:setting:`FORM_RENDERER`]] 设置中的渲染器。</p></dd></dl> |
− | <code>None</code> | ||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">value_from_datadict</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>'', ''<span class="n"><span class="pre">files</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>给定一个数据字典和这个小部件的名称,返回这个小部件的值。 <code>files</code> 可能包含来自 [[../../request-response#django.http.HttpRequest|request.FILES]] 的数据。 如果未提供值,则返回 <code>None</code>。 还要注意 <code>value_from_datadict</code> 在处理表单数据的过程中可能会被多次调用,所以如果你自定义它并添加昂贵的处理,你应该自己实现一些缓存机制。</p></dd></dl> |
− | |||
− | [[../../request-response#django.http.HttpRequest| | ||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">value_omitted_from_data</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>'', ''<span class="n"><span class="pre">files</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>给定 <code>data</code> 和 <code>files</code> 字典和这个小部件的名称,返回小部件是否有数据或文件。</p> |
− | + | <p>该方法的结果会影响模型表单 [[../../../topics/forms/modelforms#topics-modelform-save|中的字段是否回退到其默认值]] 。</p> | |
− | <p> | + | <p>特殊情况是 [[#django.forms.CheckboxInput|CheckboxInput]]、[[#django.forms.CheckboxSelectMultiple|CheckboxSelectMultiple]] 和 [[#django.forms.SelectMultiple|SelectMultiple]],它们总是返回 <code>False</code> 因为未选中的复选框和未选中的 <code><select multiple></code> '不会出现在 HTML 表单提交的数据中,因此不知道用户是否提交了值。</p></dd></dl> |
− | [[../../../topics/forms/modelforms#topics-modelform-save| | ||
− | <p> | ||
− | [[#django.forms.CheckboxSelectMultiple| | ||
− | [[#django.forms.SelectMultiple| | ||
− | <code>False</code> | ||
− | <code><select multiple></code> | ||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">use_required_attribute</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">initial</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>给定表单字段的 <code>initial</code> 值,返回是否可以使用 <code>required</code> HTML 属性呈现小部件。 表单使用此方法以及 [[../fields#django.forms.Field|Field.required]] 和 [[../api#django.forms.Form|Form.use_required_attribute]] 来确定是否为每个字段显示 <code>required</code> 属性。</p> |
− | + | <p>默认情况下,为隐藏小部件返回 <code>False</code>,否则返回 <code>True</code>。 特殊情况是 [[#django.forms.FileInput|FileInput]] 和 [[#django.forms.ClearableFileInput|ClearableFileInput]],当设置 <code>initial</code> 时返回 <code>False</code>,以及 [[#django.forms.CheckboxSelectMultiple|CheckboxSelectMultiple]],总是返回 [ X174X] 因为浏览器验证需要选中所有复选框,而不是至少选中一个。</p> | |
− | + | <p>在与浏览器验证不兼容的自定义小部件中覆盖此方法。 例如,由隐藏的 <code>textarea</code> 元素支持的 WSYSIWG 文本编辑器小部件可能希望始终返回 <code>False</code> 以避免对隐藏字段进行浏览器验证。</p> | |
− | |||
− | <p> | ||
− | |||
− | [[#django.forms.ClearableFileInput| | ||
− | <code> | ||
− | |||
− | |||
− | <p> | ||
− | |||
− | |||
− | |||
<div class="versionchanged"> | <div class="versionchanged"> | ||
− | <p> | + | <p><span class="versionmodified changed"> 3.1 版更改: </span> 在旧版本中,设置 <code>initial</code> 时为 [[#django.forms.FileInput|FileInput]] 返回 <code>True</code>。</p> |
− | [[#django.forms.FileInput| | ||
</div></dd></dl> | </div></dd></dl> | ||
第429行: | 第337行: | ||
<div id="multiwidget" class="section"> | <div id="multiwidget" class="section"> | ||
− | === | + | === MultiWidget === |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">MultiWidget</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">widgets</span></span>'', ''<span class="n"><span class="pre">attrs</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>由多个小部件组成的小部件。 [[#django.forms.MultiWidget|MultiWidget]] 与 [[../fields#django.forms|MultiValueField]] 协同工作。</p> |
− | [[#django.forms.MultiWidget| | + | <p>[[#django.forms.MultiWidget|MultiWidget]] 有一个必需的参数:</p> |
− | [[../fields#django.forms| | ||
− | <p>[[#django.forms.MultiWidget| | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">widgets</span></span></dt> |
− | <dd><p> | + | <dd><p>包含所需小部件的可迭代对象。 例如:</p> |
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> from django.forms import MultiWidget, TextInput |
− | + | >>> widget = MultiWidget(widgets=[TextInput, TextInput]) | |
− | + | >>> widget.render('name', ['john', 'paul']) | |
− | ' | + | '<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>您可以提供字典以便为每个子小部件上的 <code>name</code> 属性指定自定义后缀。 在这种情况下,对于每个 <code>(key, widget)</code> 对,密钥将附加到小部件的 <code>name</code> 以生成属性值。 您可以为单个键提供空字符串 (<code>''</code>),以抑制一个小部件的后缀。 例如:</p> |
− | |||
− | <code>(key, widget)</code> | ||
− | |||
− | |||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> widget = MultiWidget(widgets={'': TextInput, 'last': TextInput}) |
− | + | >>> widget.render('name', ['john', 'paul']) | |
− | ' | + | '<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'</syntaxhighlight> |
</div> | </div> | ||
第470行: | 第371行: | ||
</div></dd></dl> | </div></dd></dl> | ||
− | <p> | + | <p>以及一种必需的方法:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">decompress</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">value</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>此方法从字段中获取单个“压缩”值并返回“解压缩”值列表。 可以假定输入值有效,但不一定非空。</p> |
− | + | <p>这个方法'''必须由子类实现''',并且由于值可能为空,所以实现必须是防御性的。</p> | |
− | + | <p>“解压”背后的基本原理是必须将表单字段的组合值“拆分”为每个小部件的值。</p> | |
− | <p> | + | <p>这方面的一个例子是 [[#django.forms.SplitDateTimeWidget|SplitDateTimeWidget]] 如何将 <code>datetime</code> 值转换为一个列表,其中日期和时间分为两个单独的值:</p> |
− | |||
− | <p> | ||
− | |||
− | <p> | ||
− | <code>datetime</code> | ||
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from django.forms import MultiWidget |
class SplitDateTimeWidget(MultiWidget): | class SplitDateTimeWidget(MultiWidget): | ||
第496行: | 第391行: | ||
if value: | if value: | ||
return [value.date(), value.time()] | return [value.date(), value.time()] | ||
− | return [None, None]</ | + | return [None, None]</syntaxhighlight> |
</div> | </div> | ||
第503行: | 第398行: | ||
<div class="admonition tip"> | <div class="admonition tip"> | ||
− | <p> | + | <p>提示</p> |
− | <p> | + | <p>请注意, [[../fields#django.forms|MultiValueField]] 有一个补充方法 [[../fields#django.forms.MultiValueField|compress()]] 具有相反的职责 - 将所有成员字段的清理值合并为一个。</p> |
− | |||
− | |||
− | |||
</div></dd></dl> | </div></dd></dl> | ||
− | <p> | + | <p>它提供了一些自定义上下文:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">get_context</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">value</span></span>'', ''<span class="n"><span class="pre">attrs</span></span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>除了 [[#django.forms.Widget.get_context|Widget.get_context()]] 中描述的 <code>'widget'</code> 键之外,<code>MultiWidget</code> 添加了一个 <code>widget['subwidgets']</code> 键。</p> |
− | [[#django.forms.Widget.get_context| | + | <p>这些可以在小部件模板中循环:</p> |
− | <code>widget['subwidgets']</code> | ||
− | <p> | ||
<div class="highlight-html+django notranslate"> | <div class="highlight-html+django notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html+django">{% for subwidget in widget.subwidgets %} |
{% include subwidget.template_name with widget=subwidget %} | {% include subwidget.template_name with widget=subwidget %} | ||
− | {% endfor %}</ | + | {% endfor %}</syntaxhighlight> |
</div> | </div> | ||
第530行: | 第420行: | ||
</div></dd></dl> | </div></dd></dl> | ||
− | <p> | + | <p>这是一个示例小部件,它子类化 [[#django.forms.MultiWidget|MultiWidget]] 以在不同的选择框中显示带有日、月和年的日期。 此小部件旨在与 [[../fields#django.forms|DateField]] 而不是 [[../fields#django.forms|MultiValueField]] 一起使用,因此我们实现了 [[#django.forms.Widget.value_from_datadict|value_from_datadict()]]:</p> |
− | |||
− | |||
− | |||
− | [[#django.forms.Widget.value_from_datadict| | ||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">from datetime import date |
from django import forms | from django import forms | ||
第565行: | 第451行: | ||
day, month, year = super().value_from_datadict(data, files, name) | day, month, year = super().value_from_datadict(data, files, name) | ||
# DateField expects a single string that it can parse into a date. | # DateField expects a single string that it can parse into a date. | ||
− | return '{}-{}-{}'.format(year, month, day)</ | + | return '{}-{}-{}'.format(year, month, day)</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>构造函数在一个列表中创建了几个 [[#django.forms.Select|Select]] 小部件。 <code>super()</code> 方法使用此列表来设置小部件。</p> |
− | <code>super()</code> | + | <p>所需的方法 [[#django.forms.MultiWidget.decompress|decompress()]] 将 <code>datetime.date</code> 值分解为与每个小部件对应的日、月和年值。 如果选择了无效的日期,例如不存在的 2 月 30 日,则 [[../fields#django.forms|DateField]] 会向该方法传递一个字符串,因此需要解析。 当 <code>value</code> 为 <code>None</code> 时,最终的 <code>return</code> 处理,这意味着我们的子部件没有任何默认值。</p> |
− | <p> | + | <p>[[#django.forms.Widget.value_from_datadict|value_from_datadict()]] 的默认实现返回与每个 <code>Widget</code> 对应的值列表。 这适用于使用 <code>MultiWidget</code> 和 [[../fields#django.forms|MultiValueField]]。 但是由于我们想要使用带有一个 [[../fields#django.forms|DateField]] 的小部件,它接受一个值,我们已经覆盖了这个方法。 这里的实现将来自 subwidget 的数据以 [[../fields#django.forms|DateField]] 期望的格式组合成一个字符串。</p></dd></dl> |
− | <code>datetime.date</code> | ||
− | |||
− | |||
− | |||
− | <code> | ||
− | |||
− | <p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
第593行: | 第466行: | ||
<div id="built-in-widgets" class="section"> | <div id="built-in-widgets" class="section"> | ||
− | <span id=" | + | <span id="id6"></span> |
− | == | + | == 内置小部件 == |
− | Django | + | Django 提供了所有基本 HTML 小部件的表示,以及 <code>django.forms.widgets</code> 模块中一些常用的小部件组,包括 [[#text-widgets|文本输入]] 、 [[#selector-widgets|各种复选框和选择器]] , [[#file-upload-widgets|上传文件]] 和 [[#composite-widgets|处理多值输入]] 。 |
− | |||
− | |||
− | |||
− | |||
<div id="widgets-handling-input-of-text" class="section"> | <div id="widgets-handling-input-of-text" class="section"> | ||
<span id="text-widgets"></span> | <span id="text-widgets"></span> | ||
− | === | + | === 处理文本输入的小部件 === |
− | + | 这些小部件使用 HTML 元素 <code>input</code> 和 <code>textarea</code>。 | |
<div id="textinput" class="section"> | <div id="textinput" class="section"> | ||
− | ==== | + | ==== TextInput ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">TextInput</span></span> |
− | : ;* <code>input_type</code> | + | : ;* <code>input_type</code>:<code>'text'</code> |
− | ;* <code>template_name</code> | + | ;* <code>template_name</code>:<code>'django/forms/widgets/text.html'</code> |
− | ;* | + | ;* 呈现为:<code><input type="text" ...></code> |
第622行: | 第491行: | ||
<div id="numberinput" class="section"> | <div id="numberinput" class="section"> | ||
− | ==== | + | ==== NumberInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">NumberInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'number'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/number.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="number" ...></code></p></li></ul> |
− | <p> | + | <p>请注意,并非所有浏览器都支持在 <code>number</code> 输入类型中输入本地化数字。 Django 本身避免将它们用于将 [[../fields#django.forms.Field|localize]] 属性设置为 <code>True</code> 的字段。</p></dd></dl> |
− | <code>number</code> | ||
− | |||
第639行: | 第506行: | ||
<div id="emailinput" class="section"> | <div id="emailinput" class="section"> | ||
− | ==== | + | ==== EmailInput ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">EmailInput</span></span> |
− | : ;* <code>input_type</code> | + | : ;* <code>input_type</code>:<code>'email'</code> |
− | ;* <code>template_name</code> | + | ;* <code>template_name</code>:<code>'django/forms/widgets/email.html'</code> |
− | ;* | + | ;* 呈现为:<code><input type="email" ...></code> |
第650行: | 第517行: | ||
<div id="urlinput" class="section"> | <div id="urlinput" class="section"> | ||
− | ==== | + | ==== URLInput ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">URLInput</span></span> |
− | : ;* <code>input_type</code> | + | : ;* <code>input_type</code>:<code>'url'</code> |
− | ;* <code>template_name</code> | + | ;* <code>template_name</code>:<code>'django/forms/widgets/url.html'</code> |
− | ;* | + | ;* 呈现为:<code><input type="url" ...></code> |
第661行: | 第528行: | ||
<div id="passwordinput" class="section"> | <div id="passwordinput" class="section"> | ||
− | ==== | + | ==== PasswordInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">PasswordInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'password'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/password.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="password" ...></code></p></li></ul> |
− | <p> | + | <p>采用一个可选参数:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">render_value</span></span></dt> |
− | <dd><p> | + | <dd><p>确定在验证错误后重新显示表单时小部件是否将填充值(默认为 <code>False</code>)。</p></dd></dl> |
− | |||
</dd></dl> | </dd></dl> | ||
第681行: | 第547行: | ||
<div id="hiddeninput" class="section"> | <div id="hiddeninput" class="section"> | ||
− | ==== | + | ==== HiddenInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">HiddenInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'hidden'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/hidden.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="hidden" ...></code></p></li></ul> |
− | <p> | + | <p>请注意,还有一个 [[#django.forms.MultipleHiddenInput|MultipleHiddenInput]] 小部件封装了一组隐藏的输入元素。</p></dd></dl> |
− | |||
第697行: | 第562行: | ||
<div id="dateinput" class="section"> | <div id="dateinput" class="section"> | ||
− | ==== | + | ==== DateInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">DateInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'text'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/date.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="text" ...></code></p></li></ul> |
− | <p> | + | <p>采用与 [[#django.forms.TextInput|TextInput]] 相同的参数,还有一个可选参数:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">format</span></span></dt> |
− | <dd><p> | + | <dd><p>此字段的初始值将显示的格式。</p></dd></dl> |
− | <p> | + | <p>如果没有提供 <code>format</code> 参数,默认格式是在 [[#id7|:setting:`DATE_INPUT_FORMATS`]] 中找到的第一个格式,并尊重 [[../../../topics/i18n/formatting|格式本地化]] 。</p></dd></dl> |
− | |||
− | [[../../../topics/i18n/formatting| | ||
第719行: | 第582行: | ||
<div id="datetimeinput" class="section"> | <div id="datetimeinput" class="section"> | ||
− | ==== | + | ==== DateTimeInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">DateTimeInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'text'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/datetime.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="text" ...></code></p></li></ul> |
− | <p> | + | <p>采用与 [[#django.forms.TextInput|TextInput]] 相同的参数,还有一个可选参数:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">format</span></span></dt> |
− | <dd><p> | + | <dd><p>此字段的初始值将显示的格式。</p></dd></dl> |
− | <p> | + | <p>如果没有提供 <code>format</code> 参数,默认格式是在 [[#id9|:setting:`DATETIME_INPUT_FORMATS`]] 中找到的第一个格式,并尊重 [[../../../topics/i18n/formatting|格式本地化]] 。</p> |
− | + | <p>默认情况下,时间值的微秒部分始终设置为 <code>0</code>。 如果需要微秒,请使用 [[#django.forms.Widget.supports_microseconds|supports_microseconds]] 属性设置为 <code>True</code> 的子类。</p></dd></dl> | |
− | [[../../../topics/i18n/formatting| | ||
− | <p> | ||
− | |||
− | [[#django.forms.Widget.supports_microseconds| | ||
第744行: | 第603行: | ||
<div id="timeinput" class="section"> | <div id="timeinput" class="section"> | ||
− | ==== | + | ==== TimeInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">TimeInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'text'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/time.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="text" ...></code></p></li></ul> |
− | <p> | + | <p>采用与 [[#django.forms.TextInput|TextInput]] 相同的参数,还有一个可选参数:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">format</span></span></dt> |
− | <dd><p> | + | <dd><p>此字段的初始值将显示的格式。</p></dd></dl> |
− | <p> | + | <p>如果没有提供 <code>format</code> 参数,则默认格式是在 [[#id11|:setting:`TIME_INPUT_FORMATS`]] 中找到的第一个格式,并尊重 [[../../../topics/i18n/formatting|格式本地化]] 。</p> |
− | + | <p>微秒的处理见[[#django.forms.DateTimeInput|DateTimeInput]]。</p></dd></dl> | |
− | [[../../../topics/i18n/formatting| | ||
− | <p> | ||
第767行: | 第624行: | ||
<div id="textarea" class="section"> | <div id="textarea" class="section"> | ||
− | ==== | + | ==== Textarea ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">Textarea</span></span> |
− | : ;* <code>template_name</code> | + | : ;* <code>template_name</code>:<code>'django/forms/widgets/textarea.html'</code> |
− | ;* | + | ;* 呈现为:<code><textarea>...</textarea></code> |
第780行: | 第637行: | ||
<span id="selector-widgets"></span> | <span id="selector-widgets"></span> | ||
− | === | + | === 选择器和复选框小部件 === |
− | + | 这些小部件使用 HTML 元素 <code><select></code>、<code><input type="checkbox"></code> 和 <code><input type="radio"></code>。 | |
− | <code><input type="checkbox"></code> | ||
− | + | 呈现多个选项的小部件具有 <code>option_template_name</code> 属性,该属性指定用于呈现每个选项的模板。 例如,对于 [[#django.forms.Select|Select]] 小部件,<code>select_option.html</code> 为 <code><select></code> 渲染 <code><option></code>。 | |
− | |||
− | [[#django.forms.Select| | ||
− | <code>< | ||
<div id="checkboxinput" class="section"> | <div id="checkboxinput" class="section"> | ||
− | ==== | + | ==== CheckboxInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">CheckboxInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>input_type</code> | + | <li><p><code>input_type</code>:<code>'checkbox'</code></p></li> |
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/checkbox.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><input type="checkbox" ...></code></p></li></ul> |
− | <p> | + | <p>采用一个可选参数:</p> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">check_test</span></span></dt> |
− | <dd><p> | + | <dd><p>如果应选中该值的复选框,则采用 <code>CheckboxInput</code> 的值并返回 <code>True</code> 的可调用对象。</p></dd></dl> |
− | <code>True</code> | ||
</dd></dl> | </dd></dl> | ||
第812行: | 第664行: | ||
<div id="select" class="section"> | <div id="select" class="section"> | ||
− | ==== | + | ==== Select ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">Select</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/select.html'</code></p></li> |
− | <li><p><code>option_template_name</code> | + | <li><p><code>option_template_name</code>:<code>'django/forms/widgets/select_option.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:<code><select><option ...>...</select></code></p></li></ul> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">choices</span></span></dt> |
− | <dd><p> | + | <dd><p>当表单字段没有 <code>choices</code> 属性时,此属性是可选的。 如果是,它会在 [[../fields#django.forms|Field]] 上更新属性时覆盖您在此处设置的任何内容。</p></dd></dl> |
− | <code>choices</code> | ||
− | |||
</dd></dl> | </dd></dl> | ||
第832行: | 第682行: | ||
<div id="nullbooleanselect" class="section"> | <div id="nullbooleanselect" class="section"> | ||
− | ==== | + | ==== NullBooleanSelect ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">NullBooleanSelect</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/select.html'</code></p></li> |
− | <li><p><code>option_template_name</code> | + | <li><p><code>option_template_name</code>:<code>'django/forms/widgets/select_option.html'</code></p></li></ul> |
− | <p> | + | <p>选择带有“未知”、“是”和“否”选项的小部件</p></dd></dl> |
第846行: | 第696行: | ||
<div id="selectmultiple" class="section"> | <div id="selectmultiple" class="section"> | ||
− | ==== | + | ==== SelectMultiple ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">SelectMultiple</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/select.html'</code></p></li> |
− | <li><p><code>option_template_name</code> | + | <li><p><code>option_template_name</code>:<code>'django/forms/widgets/select_option.html'</code></p></li></ul> |
− | <p> | + | <p>类似于 [[#django.forms.Select|Select]],但允许多选:<code><select multiple>...</select></code></p></dd></dl> |
− | <code><select multiple>...</select></code></p></dd></dl> | ||
第861行: | 第710行: | ||
<div id="radioselect" class="section"> | <div id="radioselect" class="section"> | ||
− | ==== | + | ==== RadioSelect ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RadioSelect</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/radio.html'</code></p></li> |
− | <li><p><code>option_template_name</code> | + | <li><p><code>option_template_name</code>:<code>'django/forms/widgets/radio_option.html'</code></p></li></ul> |
− | <p> | + | <p>类似于 [[#django.forms.Select|Select]],但呈现为 <code><li></code> 标签内的单选按钮列表:</p> |
− | <code><li></code> | ||
<div class="highlight-html notranslate"> | <div class="highlight-html notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html"><ul> |
− | + | <li><input type="radio" name="..."></li> | |
... | ... | ||
− | + | </ul></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>要对生成的标记进行更精细的控制,您可以在模板中的单选按钮上循环。 假设表单 <code>myform</code> 的字段 <code>beatles</code> 使用 <code>RadioSelect</code> 作为其小部件:</p> |
− | |||
− | <code>beatles</code> | ||
<div class="highlight-html+django notranslate"> | <div class="highlight-html+django notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html+django">{% for radio in myform.beatles %} |
− | + | <div class="myradio"> | |
{{ radio }} | {{ radio }} | ||
− | + | </div> | |
− | {% endfor %}</ | + | {% endfor %}</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>这将生成以下 HTML:</p> |
<div class="highlight-html notranslate"> | <div class="highlight-html notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html"><div class="myradio"> |
− | + | <label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" required> John</label> | |
− | + | </div> | |
− | + | <div class="myradio"> | |
− | + | <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required> Paul</label> | |
− | + | </div> | |
− | + | <div class="myradio"> | |
− | + | <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" required> George</label> | |
− | + | </div> | |
− | + | <div class="myradio"> | |
− | + | <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required> Ringo</label> | |
− | + | </div></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>其中包括 <code><label></code> 标签。 要获得更详细的信息,您可以使用每个单选按钮的 <code>tag</code>、<code>choice_label</code> 和 <code>id_for_label</code> 属性。 例如,这个模板…</p> |
− | |||
− | |||
<div class="highlight-html+django notranslate"> | <div class="highlight-html+django notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html+django">{% for radio in myform.beatles %} |
− | + | <label for="{{ radio.id_for_label }}"> | |
{{ radio.choice_label }} | {{ radio.choice_label }} | ||
− | + | <span class="radio">{{ radio.tag }}</span> | |
− | + | </label> | |
− | {% endfor %}</ | + | {% endfor %}</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p>... | + | <p>...将产生以下 HTML:</p> |
<div class="highlight-html notranslate"> | <div class="highlight-html notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html"><label for="id_beatles_0"> |
John | John | ||
− | + | <span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" required></span> | |
− | + | </label> | |
− | + | <label for="id_beatles_1"> | |
Paul | Paul | ||
− | + | <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required></span> | |
− | + | </label> | |
− | + | <label for="id_beatles_2"> | |
George | George | ||
− | + | <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" required></span> | |
− | + | </label> | |
− | + | <label for="id_beatles_3"> | |
Ringo | Ringo | ||
− | + | <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required></span> | |
− | + | </label></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>如果您决定不循环使用单选按钮——例如,如果您的模板包含 <code>{{ myform.beatles }}</code>——它们将在带有 <code><li></code> 标签的 <code><ul></code> 中输出,如上所述。</p> |
− | + | <p>外部 <code><ul></code> 容器接收小部件的 <code>id</code> 属性(如果已定义),否则接收 [[../api#django.forms.BoundField|BoundField.auto_id]]。</p> | |
− | <code>< | + | <p>在单选按钮上循环时,<code>label</code> 和 <code>input</code> 标签分别包含 <code>for</code> 和 <code>id</code> 属性。 每个单选按钮都有一个 <code>id_for_label</code> 属性来输出元素的 ID。</p></dd></dl> |
− | <p> | ||
− | |||
− | <p> | ||
− | <code>for</code> | ||
− | <code>id_for_label</code> | ||
第978行: | 第817行: | ||
<div id="checkboxselectmultiple" class="section"> | <div id="checkboxselectmultiple" class="section"> | ||
− | ==== | + | ==== CheckboxSelectMultiple ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">CheckboxSelectMultiple</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/checkbox_select.html'</code></p></li> |
− | <li><p><code>option_template_name</code> | + | <li><p><code>option_template_name</code>:<code>'django/forms/widgets/checkbox_option.html'</code></p></li></ul> |
− | <p> | + | <p>类似于 [[#django.forms.SelectMultiple|SelectMultiple]],但呈现为复选框列表:</p> |
<div class="highlight-html notranslate"> | <div class="highlight-html notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="html"><ul> |
− | + | <li><input type="checkbox" name="..." ></li> | |
... | ... | ||
− | + | </ul></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>外部 <code><ul></code> 容器接收小部件的 <code>id</code> 属性(如果已定义),否则接收 [[../api#django.forms.BoundField|BoundField.auto_id]]。</p></dd></dl> |
− | |||
− | + | 与 [[#django.forms.RadioSelect|RadioSelect]] 一样,您可以遍历小部件选项的各个复选框。 与 [[#django.forms.RadioSelect|RadioSelect]] 不同,如果该字段是必需的,则复选框将不包含 <code>required</code> HTML 属性,因为浏览器验证将要求选中所有复选框,而不是至少选中一个。 | |
− | |||
− | <code>required</code> HTML | ||
− | |||
− | + | 当循环复选框时,<code>label</code> 和 <code>input</code> 标签分别包含 <code>for</code> 和 <code>id</code> 属性。 每个复选框都有一个 <code>id_for_label</code> 属性来输出元素的 ID。 | |
− | <code>for</code> | ||
− | <code>id_for_label</code> | ||
第1,017行: | 第850行: | ||
<div id="file-upload-widgets" class="section"> | <div id="file-upload-widgets" class="section"> | ||
− | <span id=" | + | <span id="id13"></span> |
− | === | + | === 文件上传小工具 === |
<div id="fileinput" class="section"> | <div id="fileinput" class="section"> | ||
− | ==== | + | ==== FileInput ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">FileInput</span></span> |
− | : ;* <code>template_name</code> | + | : ;* <code>template_name</code>:<code>'django/forms/widgets/file.html'</code> |
− | ;* | + | ;* 呈现为:<code><input type="file" ...></code> |
第1,032行: | 第865行: | ||
<div id="clearablefileinput" class="section"> | <div id="clearablefileinput" class="section"> | ||
− | ==== | + | ==== ClearableFileInput ==== |
− | ; ''class'' < | + | ; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">ClearableFileInput</span></span> |
− | : ;* <code>template_name</code> | + | : ;* <code>template_name</code>:<code>'django/forms/widgets/clearable_file_input.html'</code> |
− | ;* | + | ;* 呈现为:<code><input type="file" ...></code> 带有额外的复选框输入以清除该字段的值,如果该字段不是必需的并且具有初始数据。 |
第1,044行: | 第877行: | ||
<div id="composite-widgets" class="section"> | <div id="composite-widgets" class="section"> | ||
− | <span id=" | + | <span id="id14"></span> |
− | === | + | === 复合小部件 === |
<div id="multiplehiddeninput" class="section"> | <div id="multiplehiddeninput" class="section"> | ||
− | ==== | + | ==== MultipleHiddenInput ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">MultipleHiddenInput</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/multiple_hidden.html'</code></p></li> |
− | <li><p> | + | <li><p>呈现为:多个 <code><input type="hidden" ...></code> 标签</p></li></ul> |
− | <p> | + | <p>处理具有值列表的字段的多个隐藏小部件的小部件。</p></dd></dl> |
− | |||
第1,064行: | 第896行: | ||
<div id="splitdatetimewidget" class="section"> | <div id="splitdatetimewidget" class="section"> | ||
− | ==== | + | ==== SplitDateTimeWidget ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">SplitDateTimeWidget</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/splitdatetime.html'</code></p></li></ul> |
− | <p> | + | <p>包装器(使用 [[#django.forms.MultiWidget|MultiWidget]])围绕两个小部件:[[#django.forms.DateInput|DateInput]] 表示日期,[[#django.forms.TimeInput|TimeInput]] 表示时间。 必须与 [[../fields#django.forms|SplitDateTimeField]] 而不是 [[../fields#django.forms|DateTimeField]] 一起使用。</p> |
− | + | <p><code>SplitDateTimeWidget</code> 有几个可选参数:</p> | |
− | [[../fields#django.forms| | ||
− | <p><code>SplitDateTimeWidget</code> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">date_format</span></span></dt> |
− | <dd><p> | + | <dd><p>类似于 [[#django.forms.DateInput.format|DateInput.format]]</p></dd></dl> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">time_format</span></span></dt> |
− | <dd><p> | + | <dd><p>类似于 [[#django.forms.TimeInput.format|TimeInput.format]]</p></dd></dl> |
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">date_attrs</span></span></dt> |
<dd></dd></dl> | <dd></dd></dl> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">time_attrs</span></span></dt> |
− | <dd><p> | + | <dd><p>类似于 [[#django.forms.Widget.attrs|Widget.attrs]]。 包含要分别在呈现的 [[#django.forms.DateInput|DateInput]] 和 [[#django.forms.TimeInput|TimeInput]] 小部件上设置的 HTML 属性的字典。 如果未设置这些属性,则使用 [[#django.forms.Widget.attrs|Widget.attrs]] 代替。</p></dd></dl> |
− | |||
− | [[#django.forms.TimeInput| | ||
− | |||
</dd></dl> | </dd></dl> | ||
第1,099行: | 第926行: | ||
<div id="splithiddendatetimewidget" class="section"> | <div id="splithiddendatetimewidget" class="section"> | ||
− | ==== | + | ==== SplitHiddenDateTimeWidget ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">SplitHiddenDateTimeWidget</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/splithiddendatetime.html'</code></p></li></ul> |
− | <p> | + | <p>类似于 [[#django.forms.SplitDateTimeWidget|SplitDateTimeWidget]],但使用 [[#django.forms.HiddenInput|HiddenInput]] 作为日期和时间。</p></dd></dl> |
− | |||
第1,113行: | 第939行: | ||
<div id="selectdatewidget" class="section"> | <div id="selectdatewidget" class="section"> | ||
− | ==== | + | ==== SelectDateWidget ==== |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">SelectDateWidget</span></span></dt> |
<dd><ul> | <dd><ul> | ||
− | <li><p><code>template_name</code> | + | <li><p><code>template_name</code>:<code>'django/forms/widgets/select_date.html'</code></p></li></ul> |
− | <p> | + | <p>环绕三个 [[#django.forms.Select|Select]] 小部件:每个月、日和年各一个。</p> |
− | + | <p>采用几个可选参数:</p> | |
− | <p> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">years</span></span></dt> |
− | <dd><p> | + | <dd><p>在“年份”选择框中使用的可选年份列表/元组。 默认值为包含当前年份和未来 9 年的列表。</p></dd></dl> |
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">months</span></span></dt> |
− | <dd><p> | + | <dd><p>在“月份”选择框中使用的可选月份字典。</p> |
− | <p> | + | <p>dict 的键对应于月份编号(1-indexed),值是显示的月份:</p> |
− | |||
<div class="highlight-default notranslate"> | <div class="highlight-default notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">MONTHS = { |
1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'), | 1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'), | ||
5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'), | 5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'), | ||
9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec') | 9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec') | ||
− | }</ | + | }</syntaxhighlight> |
</div> | </div> | ||
第1,148行: | 第971行: | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">empty_label</span></span></dt> |
− | <dd><p> | + | <dd><p>如果不需要 [[../fields#django.forms|DateField]],则 [[#django.forms.SelectDateWidget|SelectDateWidget]] 将在列表顶部有一个空选项(默认为 <code>---</code>)。 您可以使用 <code>empty_label</code> 属性更改此标签的文本。 <code>empty_label</code> 可以是 <code>string</code>、<code>list</code> 或 <code>tuple</code>。 使用字符串时,所有选择框都会有一个带有此标签的空选项。 如果 <code>empty_label</code> 是 3 个字符串元素的 <code>list</code> 或 <code>tuple</code>,选择框将有自己的自定义标签。 标签应按此顺序 <code>('year_label', 'month_label', 'day_label')</code>。</p> |
− | [[#django.forms.SelectDateWidget| | ||
− | |||
− | |||
− | <code>string</code> | ||
− | |||
− | |||
− | |||
− | <code>('year_label', 'month_label', 'day_label')</code> | ||
<div class="highlight-python notranslate"> | <div class="highlight-python notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python"># A custom empty label with string |
− | field1 = forms.DateField(widget=SelectDateWidget(empty_label= | + | field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing")) |
# A custom empty label with tuple | # A custom empty label with tuple | ||
field1 = forms.DateField( | field1 = forms.DateField( | ||
widget=SelectDateWidget( | widget=SelectDateWidget( | ||
− | empty_label=( | + | empty_label=("Choose Year", "Choose Month", "Choose Day"), |
), | ), | ||
− | )</ | + | )</syntaxhighlight> |
</div> | </div> | ||
第1,183行: | 第998行: | ||
</div> | </div> | ||
+ | |||
+ | </div> | ||
+ | <div class="clearer"> | ||
+ | |||
+ | |||
</div> | </div> | ||
− | [[Category:Django 3.1.x | + | [[Category:Django 3.1.x 文档]] |
2021年10月31日 (日) 04:14的最新版本
小工具
小部件是 Django 对 HTML 输入元素的表示。 小部件处理 HTML 的呈现,以及从对应于小部件的 GET/POST 字典中提取数据。
内置小部件生成的 HTML 使用 HTML5 语法,针对 <!DOCTYPE html>
。 例如,它使用 checked
等布尔属性,而不是 checked='checked'
的 XHTML 样式。
提示
小部件不应与 表单字段 混淆。 表单字段处理输入验证的逻辑并直接在模板中使用。 小部件处理网页上 HTML 表单输入元素的呈现和原始提交数据的提取。 但是,小部件确实需要 assigned 来形成字段。
指定小部件
每当您在表单上指定字段时,Django 将使用适合要显示的数据类型的默认小部件。 要查找哪个小部件用于哪个字段,请参阅有关 内置字段类 的文档。
但是,如果您想对字段使用不同的小部件,则可以在字段定义中使用 widget 参数。 例如:
这将指定一个带有注释的表单,该表单使用更大的 Textarea 小部件,而不是默认的 TextInput 小部件。
为小部件设置参数
许多小部件都有可选的额外参数; 它们可以在定义字段上的小部件时设置。 在以下示例中,为 SelectDateWidget 设置了 years 属性:
有关哪些小部件可用以及它们接受哪些参数的更多信息,请参阅 内置小部件 。
继承自 Select 小部件的小部件
继承自 Select 小部件的小部件处理选择。 它们为用户提供了一个可供选择的选项列表。 不同的小部件以不同的方式呈现此选择; Select 小部件本身使用 <select>
HTML 列表表示,而 RadioSelect 使用单选按钮。
Select 小部件默认用于 ChoiceField 字段。 小部件上显示的选项继承自 ChoiceField,更改 ChoiceField.choices 将更新 Select.choices。 例如:
然而,提供 choices 属性的小部件可以与不基于选择的字段一起使用 - 例如 CharField - 但建议使用 ChoiceField -based field when the choices are inherent to the model and not just the representational widget.
自定义小部件实例
当 Django 将小部件呈现为 HTML 时,它只会呈现非常少的标记——Django 不会添加类名或任何其他特定于小部件的属性。 这意味着,例如,所有 TextInput 小部件在您的网页上将显示相同。
样式小部件实例
如果您想让一个小部件实例看起来与另一个不同,您需要在小部件对象实例化并分配给表单字段时指定其他属性(并且可能向您的 CSS 文件添加一些规则)。
例如,采用以下形式:
此表单将包含三个默认的 TextInput 小部件,具有默认呈现 - 没有 CSS 类,没有额外的属性。 这意味着为每个小部件提供的输入框将呈现完全相同:
在真实的 Web 页面上,您可能不希望每个小部件看起来都一样。 您可能需要更大的评论输入元素,并且您可能希望“名称”小部件具有一些特殊的 CSS 类。 还可以指定 'type' 属性以利用新的 HTML5 输入类型。 为此,您在创建小部件时使用 Widget.attrs 参数:
您还可以修改表单定义中的小部件:
或者,如果该字段未直接在表单上声明(例如模型表单字段),则可以使用 Form.fields 属性:
然后 Django 将在呈现的输出中包含额外的属性:
您还可以使用 attrs 设置 HTML id
。 有关示例,请参阅 BoundField.id_for_label。
样式小部件类
使用小部件,可以添加资产(css
和 javascript
)并更深入地自定义它们的外观和行为。
简而言之,您需要对小部件进行子类化,并 定义“媒体”内部类 或 创建“媒体”属性 。
这些方法涉及一些高级 Python 编程,并在 Form Assets 主题指南中进行了详细描述。
基本小部件类
基本小部件类 Widget 和 MultiWidget 是所有 内置小部件 的子类,可以作为自定义小部件的基础。
Widget
- class Widget(attrs=None)
这个抽象类不能被渲染,但提供了基本属性 attrs。 您还可以在自定义小部件上实现或覆盖 render() 方法。
- attrs
包含要在呈现的小部件上设置的 HTML 属性的字典。
如果您为属性分配
True
或False
的值,它将呈现为 HTML5 布尔属性:
- supports_microseconds
默认为
True
的属性。 如果设置为False
,datetime
和time
值的微秒部分将设置为0
。
- format_value(value)
清理并返回一个值以在小部件模板中使用。
value
不能保证是有效的输入,因此子类实现应该防御性地编程。
- get_context(name, value, attrs)
返回呈现小部件模板时要使用的值字典。 默认情况下,字典包含一个键,
'widget'
,它是包含以下键的小部件的字典表示:'name'
:来自name
参数的字段名称。'is_hidden'
:指示此小部件是否隐藏的布尔值。'required'
:一个布尔值,指示是否需要此小部件的字段。'value'
:format_value() 返回的值。'attrs'
:要在呈现的小部件上设置的 HTML 属性。 attrs 属性和attrs
参数的组合。'template_name'
:self.template_name
的值。
Widget
子类可以通过覆盖此方法提供自定义上下文值。
- id_for_label(id_)
给定字段的 ID,返回此小部件的 HTML ID 属性以供
<label>
使用。 如果 ID 不可用,则返回None
。这个钩子是必要的,因为一些小部件有多个 HTML 元素,因此有多个 ID。 在这种情况下,此方法应返回与小部件标签中的第一个 ID 对应的 ID 值。
- render(name, value, attrs=None, renderer=None)
使用给定的渲染器将小部件渲染为 HTML。 如果
renderer
是None
,则使用 :setting:`FORM_RENDERER` 设置中的渲染器。
- value_from_datadict(data, files, name)
给定一个数据字典和这个小部件的名称,返回这个小部件的值。
files
可能包含来自 request.FILES 的数据。 如果未提供值,则返回None
。 还要注意value_from_datadict
在处理表单数据的过程中可能会被多次调用,所以如果你自定义它并添加昂贵的处理,你应该自己实现一些缓存机制。
- value_omitted_from_data(data, files, name)
给定
data
和files
字典和这个小部件的名称,返回小部件是否有数据或文件。该方法的结果会影响模型表单 中的字段是否回退到其默认值 。
特殊情况是 CheckboxInput、CheckboxSelectMultiple 和 SelectMultiple,它们总是返回
False
因为未选中的复选框和未选中的<select multiple>
'不会出现在 HTML 表单提交的数据中,因此不知道用户是否提交了值。
- use_required_attribute(initial)
给定表单字段的
initial
值,返回是否可以使用required
HTML 属性呈现小部件。 表单使用此方法以及 Field.required 和 Form.use_required_attribute 来确定是否为每个字段显示required
属性。默认情况下,为隐藏小部件返回
False
,否则返回True
。 特殊情况是 FileInput 和 ClearableFileInput,当设置initial
时返回False
,以及 CheckboxSelectMultiple,总是返回 [ X174X] 因为浏览器验证需要选中所有复选框,而不是至少选中一个。在与浏览器验证不兼容的自定义小部件中覆盖此方法。 例如,由隐藏的
textarea
元素支持的 WSYSIWG 文本编辑器小部件可能希望始终返回False
以避免对隐藏字段进行浏览器验证。3.1 版更改: 在旧版本中,设置
initial
时为 FileInput 返回True
。
MultiWidget
- class MultiWidget(widgets, attrs=None)
由多个小部件组成的小部件。 MultiWidget 与 MultiValueField 协同工作。
MultiWidget 有一个必需的参数:
- widgets
包含所需小部件的可迭代对象。 例如:
您可以提供字典以便为每个子小部件上的
name
属性指定自定义后缀。 在这种情况下,对于每个(key, widget)
对,密钥将附加到小部件的name
以生成属性值。 您可以为单个键提供空字符串 (),以抑制一个小部件的后缀。 例如:
以及一种必需的方法:
- decompress(value)
此方法从字段中获取单个“压缩”值并返回“解压缩”值列表。 可以假定输入值有效,但不一定非空。
这个方法必须由子类实现,并且由于值可能为空,所以实现必须是防御性的。
“解压”背后的基本原理是必须将表单字段的组合值“拆分”为每个小部件的值。
这方面的一个例子是 SplitDateTimeWidget 如何将
datetime
值转换为一个列表,其中日期和时间分为两个单独的值:提示
请注意, MultiValueField 有一个补充方法 compress() 具有相反的职责 - 将所有成员字段的清理值合并为一个。
它提供了一些自定义上下文:
- get_context(name, value, attrs)
除了 Widget.get_context() 中描述的
'widget'
键之外,MultiWidget
添加了一个widget['subwidgets']
键。这些可以在小部件模板中循环:
这是一个示例小部件,它子类化 MultiWidget 以在不同的选择框中显示带有日、月和年的日期。 此小部件旨在与 DateField 而不是 MultiValueField 一起使用,因此我们实现了 value_from_datadict():
构造函数在一个列表中创建了几个 Select 小部件。
super()
方法使用此列表来设置小部件。所需的方法 decompress() 将
datetime.date
值分解为与每个小部件对应的日、月和年值。 如果选择了无效的日期,例如不存在的 2 月 30 日,则 DateField 会向该方法传递一个字符串,因此需要解析。 当value
为None
时,最终的return
处理,这意味着我们的子部件没有任何默认值。value_from_datadict() 的默认实现返回与每个
Widget
对应的值列表。 这适用于使用MultiWidget
和 MultiValueField。 但是由于我们想要使用带有一个 DateField 的小部件,它接受一个值,我们已经覆盖了这个方法。 这里的实现将来自 subwidget 的数据以 DateField 期望的格式组合成一个字符串。
内置小部件
Django 提供了所有基本 HTML 小部件的表示,以及 django.forms.widgets
模块中一些常用的小部件组,包括 文本输入 、 各种复选框和选择器 , 上传文件 和 处理多值输入 。
处理文本输入的小部件
这些小部件使用 HTML 元素 input
和 textarea
。
TextInput
- class TextInput
- ;*
input_type
:'text'
template_name
:'django/forms/widgets/text.html'
- 呈现为:
<input type="text" ...>
NumberInput
- class NumberInput
input_type
:'number'
template_name
:'django/forms/widgets/number.html'
呈现为:
<input type="number" ...>
请注意,并非所有浏览器都支持在
number
输入类型中输入本地化数字。 Django 本身避免将它们用于将 localize 属性设置为True
的字段。
EmailInput
- class EmailInput
- ;*
input_type
:'email'
template_name
:'django/forms/widgets/email.html'
- 呈现为:
<input type="email" ...>
URLInput
- class URLInput
- ;*
input_type
:'url'
template_name
:'django/forms/widgets/url.html'
- 呈现为:
<input type="url" ...>
PasswordInput
- class PasswordInput
input_type
:'password'
template_name
:'django/forms/widgets/password.html'
呈现为:
<input type="password" ...>
采用一个可选参数:
- render_value
确定在验证错误后重新显示表单时小部件是否将填充值(默认为
False
)。
DateInput
- class DateInput
input_type
:'text'
template_name
:'django/forms/widgets/date.html'
呈现为:
<input type="text" ...>
采用与 TextInput 相同的参数,还有一个可选参数:
- format
此字段的初始值将显示的格式。
如果没有提供
format
参数,默认格式是在 :setting:`DATE_INPUT_FORMATS` 中找到的第一个格式,并尊重 格式本地化 。
DateTimeInput
- class DateTimeInput
input_type
:'text'
template_name
:'django/forms/widgets/datetime.html'
呈现为:
<input type="text" ...>
采用与 TextInput 相同的参数,还有一个可选参数:
- format
此字段的初始值将显示的格式。
如果没有提供
format
参数,默认格式是在 :setting:`DATETIME_INPUT_FORMATS` 中找到的第一个格式,并尊重 格式本地化 。默认情况下,时间值的微秒部分始终设置为
0
。 如果需要微秒,请使用 supports_microseconds 属性设置为True
的子类。
TimeInput
- class TimeInput
input_type
:'text'
template_name
:'django/forms/widgets/time.html'
呈现为:
<input type="text" ...>
采用与 TextInput 相同的参数,还有一个可选参数:
- format
此字段的初始值将显示的格式。
如果没有提供
format
参数,则默认格式是在 :setting:`TIME_INPUT_FORMATS` 中找到的第一个格式,并尊重 格式本地化 。微秒的处理见DateTimeInput。
Textarea
- class Textarea
- ;*
template_name
:'django/forms/widgets/textarea.html'
- 呈现为:
<textarea>...</textarea>
- 呈现为:
选择器和复选框小部件
这些小部件使用 HTML 元素 <select>
、<input type="checkbox">
和 <input type="radio">
。
呈现多个选项的小部件具有 option_template_name
属性,该属性指定用于呈现每个选项的模板。 例如,对于 Select 小部件,select_option.html
为 <select>
渲染 <option>
。
CheckboxInput
- class CheckboxInput
input_type
:'checkbox'
template_name
:'django/forms/widgets/checkbox.html'
呈现为:
<input type="checkbox" ...>
采用一个可选参数:
- check_test
如果应选中该值的复选框,则采用
CheckboxInput
的值并返回True
的可调用对象。
Select
- class Select
template_name
:'django/forms/widgets/select.html'
option_template_name
:'django/forms/widgets/select_option.html'
呈现为:
<select><option ...>...</select>
- choices
当表单字段没有
choices
属性时,此属性是可选的。 如果是,它会在 Field 上更新属性时覆盖您在此处设置的任何内容。
NullBooleanSelect
- class NullBooleanSelect
template_name
:'django/forms/widgets/select.html'
option_template_name
:'django/forms/widgets/select_option.html'
选择带有“未知”、“是”和“否”选项的小部件
SelectMultiple
- class SelectMultiple
template_name
:'django/forms/widgets/select.html'
option_template_name
:'django/forms/widgets/select_option.html'
类似于 Select,但允许多选:
<select multiple>...</select>
RadioSelect
- class RadioSelect
template_name
:'django/forms/widgets/radio.html'
option_template_name
:'django/forms/widgets/radio_option.html'
类似于 Select,但呈现为
<li>
标签内的单选按钮列表:要对生成的标记进行更精细的控制,您可以在模板中的单选按钮上循环。 假设表单
myform
的字段beatles
使用RadioSelect
作为其小部件:这将生成以下 HTML:
其中包括
<label>
标签。 要获得更详细的信息,您可以使用每个单选按钮的tag
、choice_label
和id_for_label
属性。 例如,这个模板…...将产生以下 HTML:
如果您决定不循环使用单选按钮——例如,如果您的模板包含
模板:Myform.beatles
——它们将在带有<li>
标签的<ul>
中输出,如上所述。外部
<ul>
容器接收小部件的id
属性(如果已定义),否则接收 BoundField.auto_id。在单选按钮上循环时,
label
和input
标签分别包含for
和id
属性。 每个单选按钮都有一个id_for_label
属性来输出元素的 ID。
CheckboxSelectMultiple
- class CheckboxSelectMultiple
template_name
:'django/forms/widgets/checkbox_select.html'
option_template_name
:'django/forms/widgets/checkbox_option.html'
类似于 SelectMultiple,但呈现为复选框列表:
外部
<ul>
容器接收小部件的id
属性(如果已定义),否则接收 BoundField.auto_id。
与 RadioSelect 一样,您可以遍历小部件选项的各个复选框。 与 RadioSelect 不同,如果该字段是必需的,则复选框将不包含 required
HTML 属性,因为浏览器验证将要求选中所有复选框,而不是至少选中一个。
当循环复选框时,label
和 input
标签分别包含 for
和 id
属性。 每个复选框都有一个 id_for_label
属性来输出元素的 ID。
文件上传小工具
FileInput
- class FileInput
- ;*
template_name
:'django/forms/widgets/file.html'
- 呈现为:
<input type="file" ...>
- 呈现为:
ClearableFileInput
- class ClearableFileInput
- ;*
template_name
:'django/forms/widgets/clearable_file_input.html'
- 呈现为:
<input type="file" ...>
带有额外的复选框输入以清除该字段的值,如果该字段不是必需的并且具有初始数据。
- 呈现为:
复合小部件
SplitDateTimeWidget
- class SplitDateTimeWidget
template_name
:'django/forms/widgets/splitdatetime.html'
包装器(使用 MultiWidget)围绕两个小部件:DateInput 表示日期,TimeInput 表示时间。 必须与 SplitDateTimeField 而不是 DateTimeField 一起使用。
SplitDateTimeWidget
有几个可选参数:- date_format
类似于 DateInput.format
- time_format
类似于 TimeInput.format
- date_attrs
- time_attrs
类似于 Widget.attrs。 包含要分别在呈现的 DateInput 和 TimeInput 小部件上设置的 HTML 属性的字典。 如果未设置这些属性,则使用 Widget.attrs 代替。
SelectDateWidget
- class SelectDateWidget
template_name
:'django/forms/widgets/select_date.html'
环绕三个 Select 小部件:每个月、日和年各一个。
采用几个可选参数:
- years
在“年份”选择框中使用的可选年份列表/元组。 默认值为包含当前年份和未来 9 年的列表。
- months
在“月份”选择框中使用的可选月份字典。
dict 的键对应于月份编号(1-indexed),值是显示的月份:
- empty_label
如果不需要 DateField,则 SelectDateWidget 将在列表顶部有一个空选项(默认为
---
)。 您可以使用empty_label
属性更改此标签的文本。empty_label
可以是string
、list
或tuple
。 使用字符串时,所有选择框都会有一个带有此标签的空选项。 如果empty_label
是 3 个字符串元素的list
或tuple
,选择框将有自己的自定义标签。 标签应按此顺序('year_label', 'month_label', 'day_label')
。