Opened 9 months ago

Closed 9 months ago

Last modified 9 months ago

#35191 closed New feature (wontfix)

Allow form renderer to use custom template for label tag

Reported by: Oxan van Leeuwen Owned by: Almaz
Component: Forms Version: 5.0
Severity: Normal Keywords: forms render template
Cc: David Smith, Oxan van Leeuwen Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Currently, a form renderer can't easily change the template used by the BoundField.label_tag() method: template_name_label can be set on the form, but there exists no label_template_name on the FormRenderer that it fallbacks to.

This is problematic if e.g. CSS classes need to be set on the form labels. Writing out the <label> tag in the template instead of calling label_tag() is also not an option, as label_tag() does somewhat complex processing to ensure the correct id (and label) are used.

Change History (5)

comment:1 by Almaz, 9 months ago

Owner: changed from nobody to Almaz
Status: newassigned

comment:2 by Mariusz Felisiak, 9 months ago

Cc: David Smith added
Easy pickings: unset
Resolution: wontfix
Status: assignedclosed
Type: Cleanup/optimizationNew feature

I don't think a new attribute is needed. You can always override the default template as any other template in your project.

comment:3 by Oxan van Leeuwen, 9 months ago

The problem with overriding the default template is that it's global to the project, while form renderers are local to the form. This is useful e.g. if multiple different form layouts are used within a project, or when incrementally transitioning between design systems. There's also the matter of consistency: the form, formset and field templates can already be changed by the renderer, why not the label? After all, the default template for those could also be globally overridden.

Last edited 9 months ago by Oxan van Leeuwen (previous) (diff)

comment:4 by Mariusz Felisiak, 9 months ago

There's also the matter of consistency: the form, formset and field templates can already be changed by the renderer, why not the label?

There are also many templates that the renderer cannot override, such as ErrorDict or ErrorList templates. There are also many templates that the renderer cannot override, such as ErrorDict or ErrorList templates. Adding a new customization option is always a bit controversial (we already have many of them).

comment:5 by Oxan van Leeuwen, 9 months ago

I agree there are more templates that the renderer can't override, but in practice those are less of a problem, as it's easy to just not use them in your form and field templates. For example ErrorDict and ErrorList are thin wrappers around dict and list respectively, and you can iterate over those directly in the field template to generate an error list in whatever style you want. That's not the case for the label template, as BoundField.label_tag() contains (among other things) somewhat complex logic to generate the value for the for attribute that can't easily be replicated in a template. Furthermore, even if you do replicate it, I'd be worried about that logic being considered an implementation detail and changing in a future version of Django.

What would also work is to extract the logic that generates the id and contents from label_tag() out into separate methods (or properties) of BoundField, which can then be used directly in the field template.

The wider context here (and also behind #35192) is that I'm trying to implement something that renders forms in a way that's usable with existing frontend frameworks (such as Bootstrap or Tailwind). Current attempts at this (such as django-crispy-forms or django-bootstrap5) all render using a custom template tag, whose implementation pokes around in the internals of the forms component. In my experience those always have hardcoded special casing and can't support the full feature set and extensibility of the forms component. It'd be great if something like that could be implemented in plain Django, working along with instead of around the forms component. Form renderers seem like the logical extension point for such an implementation, and they're nearly there, but at the moment they are a bit too inflexible to cleanly allow all necessary customization.
However, I do think both of these issues have a wider impact than just this project of mine, and resolving them will also be useful for others that want to customize form rendering in different ways.

Last edited 9 months ago by Oxan van Leeuwen (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top