#31026 closed Cleanup/optimization (fixed)
Switch form rendering to template engine
Reported by: | Johannes Maron | Owned by: | David Smith |
---|---|---|---|
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
We recently switched widgets to use the template engine and template that can be overwritten.
That is currently not the case for forms themselves. More precisely django.forms.BaseForm.as_table
and it's siblings.
They use string modulation, that they pass on to the _html_output
, which generates the context.
I would propose to change the behavior the following way:
Have _html_output
produce a context and don't actually perform a render.
have each as_XYZ
method get the context and perform a template based render.
This allows to overwrite or add a new as_XY
method and inject something into the context or change the template.
This is also an opportunity to simplify the code. Since templates to render attributes already exist.
Change History (36)
comment:1 by , 5 years ago
Has patch: | set |
---|
comment:2 by , 5 years ago
Triage Stage: | Unreviewed → Accepted |
---|
I think that it makes sense. It'd be great if you could do a bit of research on #15667 to figure if this was simply overlooked or if there was a reason for not doing it in the first place.
I think there's also a ticket out there to allow Form.__str__()
to use as_p
or as_ul
instead of as_table
by default. If we were using template based rendering we could simply define a django/forms/default.html
that {% include "django/forms/table.html" %}
, use it in .__str__()
, and document that the former must be overridden to achieve the desired behaviour.
comment:3 by , 5 years ago
Yes, I'll take some time next week to do some research.
The default idea, is great. That would make it even more versatile, love it!
comment:4 by , 5 years ago
With that change I'd also like to drop [error_class]https://docs.djangoproject.com/en/2.2/ref/forms/api/#customizing-the-error-list-format support, since this would be a template too. However, this is a documented API, though not widely used. I will work around it for now, but I'd really like to remove it.
comment:5 by , 5 years ago
Ok, I have a working patch now. It does not change tests, or removes much code to prove its backwards compatible.
However, I'd like to introduce some changes, to improve the resulting architecture and output.
- Change the position of hidden inputs. Currently, they are injected at a certain index. I'd like to simply amend them. It would greatly simplify the templates. Since they are hidden, it shouldn't change browser rendering.
- I'd like to deprecate the now unused
django.forms.BaseForm._html_output
. Yes, it is private, but we have tests running against it and it's referenced in some tickets. This gives me the impression is more commonly used than we'd like. - I'd like to deprecate
django.forms.boundfield.BoundField.label_tag
. The label can be generated with a template with a simple include. I believe this to be the better implementation. - Errors I would not change. I am not 100% happy with the design, however, it is based on templates now, which makes adding changes simple.
I haven't written any documentation yet, this will be another monster task. I'd like to get some feedback on the code side first, to avoid back and forth.
comment:6 by , 5 years ago
Patch needs improvement: | set |
---|
comment:7 by , 5 years ago
Patch needs improvement: | unset |
---|
comment:8 by , 5 years ago
Needs documentation: | set |
---|
comment:9 by , 5 years ago
Patch needs improvement: | set |
---|
comment:10 by , 5 years ago
Needs documentation: | unset |
---|---|
Patch needs improvement: | unset |
comment:11 by , 5 years ago
I'm looking at the PR now, but I'll put this initial comment here, so it doesn't get lost:
Change the position of hidden inputs. Currently, they are injected at a certain index. I'd like to simply amend them. It would greatly simplify the templates. Since they are hidden, it shouldn't change browser rendering.
From experience with Crispy Forms, I'm doubtful that we can just move hidden fields to the end. Rendering, yes, would be unaffected. But the resultant data-dict would not be. With multi-value fields, as first thought, order does matter. (I can't count the number of times we've seen issues resolving around exact rendered field order on Crispy Forms...)
Open to be shown wrong here but... 😬
comment:12 by , 5 years ago
OK, scrub that last comment: existing rendering is already placing hidden fields last, so data-dict is unaffected too.
comment:13 by , 5 years ago
Yes, I can confirm this is the case. I actually prefer the new HTML output, since we don't just amend hidden fields within the parent of another field.
So all this needs is a thorough review ;) Can't review it myself, but I am trading :P
comment:14 by , 5 years ago
Needs documentation: | set |
---|---|
Needs tests: | set |
Patch needs improvement: | set |
comment:15 by , 4 years ago
Needs tests: | unset |
---|---|
Patch needs improvement: | unset |
comment:16 by , 4 years ago
Needs documentation: | unset |
---|
I'm going to uncheck the Needs Documentation to put this back in the review queue.
comment:17 by , 3 years ago
Patch needs improvement: | set |
---|
comment:18 by , 3 years ago
Patch needs improvement: | unset |
---|
comment:19 by , 3 years ago
Owner: | changed from | to
---|
comment:20 by , 3 years ago
Patch needs improvement: | set |
---|
comment:24 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
I drafted something, to add more context, to what I am proposing: https://github.com/django/django/pull/12133/files