在我的 settings.py 中,我已设置
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
现在可以添加我自己的模板:
<project>/templates/django/forms/widgets/
或
<app>/templates/django/forms/widgets/
这很棒!但是,我无法找到的是在哪里覆盖默认的html(表单)标签?
class TestForm(forms.Form):
first_name = forms.CharField(label="First name", max_length=50)
last_name = forms.CharField(label="Last name")
nick_name = forms.CharField(required=False)
上面的表单会呈现这样的标签:
<label for="id_first_name">First name:</label>
我想以不同的方式呈现标签。所以,我认为添加html标签模板会很容易: templates / django / forms / widgets / label.html
没有工作。正在浏览Django文档,但我无法找到如何为标签执行此操作。显然,标签不是小部件。
我的问题,我在哪里/如何更改默认标签?
答案 0 :(得分:2)
这是一个可行的解决方案(已在Django 3.1上测试):
创建Django表单的子类,然后将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)
# Only add the suffix if the label does not end in punctuation.
# Translators: If found as last label character, these punctuation
# characters will prevent the default label_suffix to be appended to the label
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">First name:</p>
答案 1 :(得分:0)
实际上可以覆盖Django中现有的表单小部件。
首先,您需要将'django.forms'
添加到INSTALLED_APPS
才能将其视为应用。
INSTALLED_APPS = [
...
"django.forms",
...
]
然后将FORM_RENDERER
附加到您的 settings.py
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
有关TemplatesSetting的更多信息可以在Django文档中找到。
然后,将您要覆盖的所有小部件文件从django/forms/widgets/
文件夹复制到您自己的projectname/templates/django/forms/widgets
文件夹。自定义!
我希望这会有所帮助。
答案 2 :(得分:0)
您可以覆盖以下格式的__init__()
方法:
def __init__(self, *args, **kwargs):
self.fields['field_name'].label = 'Your new label here'