以下是一个测试通过的解决方案(在 Django 3.1 上测试通过):
创建一个 Django 表单(Form)的子类,并将 LABEL_TEMPLATE
设置为您想要的模板。
myapp/base_form.py
from django import forms
from django.forms.utils import flatatt
from django.utils.html import conditional_escape, format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
LABEL_TEMPLATE = '<p{}>{}</p>'
class CustomLabelBoundField(forms.boundfield.BoundField):
def label_tag(self, contents=None, attrs=None, label_suffix=None):
"""
Wrap the given contents in a <label>, if the field has an ID attribute.
contents should be mark_safe'd to avoid HTML escaping. If contents
aren't given, use the field's HTML-escaped label.
If attrs are given, use them as HTML attributes on the <label> tag.
label_suffix overrides the form's label_suffix.
"""
contents = contents or self.label
if label_suffix is None:
label_suffix = (self.field.label_suffix if self.field.label_suffix is not None
else self.form.label_suffix)
if label_suffix and contents and contents[-1] not in _(':?.!'):
contents = format_html('{}{}', contents, label_suffix)
widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id
if id_:
id_for_label = widget.id_for_label(id_)
if id_for_label:
attrs = {**(attrs or {}), 'for': id_for_label}
if self.field.required and hasattr(self.form, 'required_css_class'):
attrs = attrs or {}
if 'class' in attrs:
attrs['class'] += ' ' + self.form.required_css_class
else:
attrs['class'] = self.form.required_css_class
attrs = flatatt(attrs) if attrs else ''
contents = format_html(LABEL_TEMPLATE, attrs, contents)
else:
contents = conditional_escape(contents)
return mark_safe(contents)
def get_bound_field(field, form, field_name):
"""
Return a BoundField instance that will be used when accessing the form
field in a template.
"""
return CustomLabelBoundField(form, field, field_name)
class CustomLabelForm(forms.Form):
def __getitem__(self, name):
"""Return a BoundField with the given name."""
try:
field = self.fields[name]
except KeyError:
raise KeyError(
"Key '%s' not found in '%s'. Choices are: %s." % (
name,
self.__class__.__name__,
', '.join(sorted(self.fields)),
)
)
if name not in self._bound_fields_cache:
self._bound_fields_cache[name] = get_bound_field(field, self, name)
return self._bound_fields_cache[name]
继承自 CustomLabelForm
的表单:
myapp/forms.py
from django import forms
from myapp.base_form import CustomLabelForm
class TestForm(CustomLabelForm):
first_name = forms.CharField(label="First name", max_length=50)
last_name = forms.CharField(label="Last name")
nick_name = forms.CharField(required=False)
这将产生
<p for="id_first_name">名字:</p>
。
label{width:200px;...}
。当你想要正确地样式化表单时,我建议使用Widget-Tweaks。这是Django表单最个性化的样式选项,因为你可以在每个表单属性上使用纯CSS。请参见我的答案此处。 - hansTheFranz