注意:希望即将到来的 Django 4.0 将使这一切变得更容易,因为它提供了基于模板的表单渲染。
直到那时:
OP 要求一种在表单定义中使用BoundField.label_tag()的方法。
user240515和user2732686的回答确实提供了一些实施建议,但没有提供任何理由。大多数其他基于自定义模板标签的解决方案都需要我们手动渲染表单字段,因此如果我们只是想使用{{ form }}
.
因此,除了所有这些答案之外,这里还尝试提供更多背景信息。
关于 label_tag
表单标签由BaseForm.as_table()
、as_ul()
或as_p()
快捷方式通过“私有”BaseForm._html_output()
方法呈现,如源代码所示。
这是通过调用来完成的BoundField.label_tag()
,如这里所示。label_tag ()方法接受一个attrs
带有标记的附加 HTML 属性的参数<label>
。
但是,问题在于没有, 的BaseForm._html_output()
调用,并且没有简单的替代方法来设置参数。label_tag()
attrs
attrs
如何扩展 label_tag?
Django通过扩展其方法contrib.admin
解决了这个问题,从源代码中可以清楚地看出。label_tag()
AdminField
为了扩展BoundField.label_tag()
,我们可以创建一个自定义的 BoundField:
class MyBoundField(forms.BoundField):
def __init__(self, form, field, name, label_attrs=None):
super().__init__(form, field, name)
self.label_attrs = label_attrs
def label_tag(self, contents=None, attrs=None, label_suffix=None):
if attrs is None:
attrs = dict()
attrs.update(self.label_attrs or {})
return super().label_tag(contents, attrs, label_suffix)
现在我们可以创建一个带有特定标签属性的绑定字段,但是我们如何处理它呢?
如何使用自定义绑定字段?
绑定字段是使用forms.Field.get_bound_field()实例化的,因此,我们可以重写该方法以返回我们的自定义绑定字段:
class MyField(forms.Field):
# note typically we would use any of django's forms.Field subclasses
def __init__(self, *args, **kwargs):
# we could also set label_attrs here, based on the field properties
self.label_attrs = kwargs.pop('label_attrs', None)
super().__init__(*args, **kwargs)
def get_bound_field(self, form, field_name):
return MyBoundField(
form=form, field=self, name=field_name, label_attrs=self.label_attrs)
然后我们可以使用我们的自定义字段Form
:
class MyForm(forms.Form):
some_field = MyField(..., label_attrs={'class': 'my-class'})
但是如果我们想对所有的表单域都这样做呢?
如何为所有表单字段使用自定义绑定字段?
最后,Field.get_bound_field()
被调用BaseForm.__getitem__()
(参见源代码)。这意味着我们可以通过调用 eg 来获得一个绑定字段my_form['some_field']
。
为了对所有表单字段使用我们的自定义绑定字段,我们可以为表单中的所有字段添加猴子补丁 field.get_bound_field
,或者我们可以覆盖表单__getitem__()
以忽略get_bound_field()
并直接使用MyBoundField
。
这是一个覆盖的示例,它主要是原始 source的副本,除了以下MyBoundField
行:
class MyForm(forms.Form):
label_attrs = {'class': 'my-class'}
def __getitem__(self, name):
"""Return a MyBoundField with the given name."""
try:
field = self.fields[name]
except KeyError:
... # left out for clarity
if name not in self._bound_fields_cache:
self._bound_fields_cache[name] = MyBoundField(
form=self, field=field, name=name, label_attrs=self.label_attrs)
return self._bound_fields_cache[name]
最后,这对于一些造型来说似乎很麻烦。