[Fixed]-Django override the form HTML label template?

3👍

Here is a working solution (tested on Django 3.1) :

Create a child class of Django’s Form, and set LABEL_TEMPLATE to the template your want.

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]

And inherit your form from 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)


This produces <p for="id_first_name">First name:</p>

3👍

You could override __init__() method of the form:

def __init__(self, *args, **kwargs):
    self.fields['field_name'].label = 'Your new label here'

1👍

Overriding existing form widgets in Django can actually be done.

First you need to add 'django.forms' to your INSTALLED_APPS to treat it as an app.

INSTALLED_APPS = [
    ...
    "django.forms",
    ...
]

Then append FORM_RENDERER to your settings.py

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

More info on TemplatesSetting can be found on the Django docs.

After that, copy any widget files you’d like to override from the django/forms/widgets/ folder to your own projectname/templates/django/forms/widgets folder. Customize away!

I hope this helps.

Leave a comment