Django覆盖表单HTML标签模板?

时间:2017-07-26 09:24:37

标签: django django-forms django-templates

在我的 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文档,但我无法找到如何为标签执行此操作。显然,标签不是小部件。

lodash

我的问题,我在哪里/如何更改默认标签?

3 个答案:

答案 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'