#35987 closed Bug (fixed)
ErrorList.copy() reverts to default renderer
| Reported by: | Adam Johnson | Owned by: | Adam Johnson |
|---|---|---|---|
| Component: | Forms | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When an ErrorList is copied, it loses track of any custom renderer, reverting to the default one. Practically, this means custom styles are not applied to non-field errors when rendering a whole form.
For example, I wrote a custom renderer that swaps some templates like so:
from django import forms from django.forms.renderers import TemplatesSetting from django.template.exceptions import TemplateDoesNotExist class CustomRenderer(TemplatesSetting): def get_template(self, template_name): if template_name.startswith("django/forms/"): # Load our custom version from "custom/forms/" if it exists our_template = f"custom/{template_name.removeprefix('django/')}" try: return super().get_template(our_template) except TemplateDoesNotExist: pass return super().get_template(template_name) class MyForm(forms.Form): default_renderer = CustomRenderer()
The custom error list template uses some CSS utility classes from Tailwind, like text-red-600:
{% if errors %}<ul class="text-red-600">{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}
Creating a form with a non-field error and rendering those errors uses the custom template:
In [1]: from example.forms import MyForm ...: ...: form = MyForm({}) ...: form.full_clean() ...: form.add_error(None, "Test error") In [2]: form.non_field_errors().render() Out[2]: '<ul class="text-red-600"><li>Test error</li></ul>'
But rendering the whole form reverts to the default template, from the default renderer:
In [3]: form.render() Out[3]: '<ul class="errorlist nonfield"><li>Test error</li></ul>\n\n <div></div>'
This occurs because the ErrorList is copied in Form.get_context():
The fix would be to also copy over renderer in ErrorList.copy():
I think this has probably been an issue ever since a custom renderer became possible in #31026.
Change History (5)
comment:1 by , 11 months ago
| Has patch: | set |
|---|
comment:2 by , 11 months ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 11 months ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Thank you!