Django 覆盖表单 HTML 标签模板?
Posted
技术标签:
【中文标题】Django 覆盖表单 HTML 标签模板?【英文标题】:Django override the form HTML label template? 【发布时间】:2018-01-01 12:40:53 【问题描述】:在我的 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 文档,但我找不到如何为标签执行此操作。显然标签不是小部件。
https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#built-in-widgets
我的问题,我在哪里/如何更改默认标签?
【问题讨论】:
当它只是你想要设置样式的标签时,你可以进入 CSS 并写labelwidth:200px;...
当你想要正确设置表单样式时,我建议使用 Widget-Tweaks。它是 Django 表单最个性化的样式选项,因为您可以在每个表单属性上使用纯 css。看我的回答here
@hansTheFranz 谢谢。但我不是在造型之后,我想重写标签。例如,不是
您是正确的,标签不是小部件。
【参考方案1】:
这是一个可行的解决方案(在 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>
【讨论】:
【参考方案2】:您可以覆盖表单的__init__()
方法:
def __init__(self, *args, **kwargs):
self.fields['field_name'].label = 'Your new label here'
【讨论】:
【参考方案3】:实际上可以在 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
文件夹中。自定义吧!
我希望这会有所帮助。
【讨论】:
以上是关于Django 覆盖表单 HTML 标签模板?的主要内容,如果未能解决你的问题,请参考以下文章