#34077 closed New feature (fixed)
Make BoundField renderable.
Reported by: | David Smith | Owned by: | David Smith |
---|---|---|---|
Component: | Forms | Version: | 4.1 |
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
As of Django 4.1 Forms and Widgets (i.e. its <input>
) are renderable using the template engine. Django also has a strong concept of a field with the BoundField
class. This contains all of the information required to render a field such as its label, errors, help text and its Widget.
Currently something like this is possible:
{% for field in form %} {{ field.label_tag }} {{ field }} # Note this is the widget! {{ field.help_text }} {% endfor %}
The current limitation is that each component of each field needs to be rendered individually. It's fine when they are rendered all in the same way as we can put them in a nice loop like above.
However, a reasonable request could be to have the first name
and last name
on the same row (say). This would result in needing to do something like the following. This would become even more verbose with errors being introduced too:
<div class="row"> <div class="col"> {{ form.first_name.label }} {{ form.first_name }} {{ form.first_name.help_text }} </div> <div class="col"> {{ form.last_name.label }} {{ form.last_name }} {{ form.last_name.help_text }} </div> </div> <div> # more fields here </div>
The proposal is that the BoundField
should be a renderable object, this could either be done by a new method (e.g. field.as_field
) or maybe a template filter (e.g field|as_field
). We need the as_field
(or another function name) as the field on it's own currently renders the fields widget rather than the whole field (i.e. incl label, help text , errors).
This would allow the above to be written as:
<div class="row"> <div class="col"> {{ form.first_name|as_field }} </div> <div class="col"> {{ form.last_name|as_field }} </div> </div> <div> # more fields here </div>
A few initial thoughts on a possible implementation approach. This is not fully thought out, but should hopefully be a helpful rough guide.
- Field would learn a
template_name
attribute which can also be set via it's__init__
. Therefore in a form you would have:
class MyForm(forms.Form) first_name = forms.CharField(max=10, template_name="my_template_name.html")
- Add a new method, either as a filter or as a new method to BoundField which renders the
BoundField
with it's fields template (boundfield.field.template_name
)
- Consider if we need to provide a default implementation of this. If so we should replicate the
div.html
templates. Specifically these lines. Thediv.html
template can be updated to use this new method.
- If we do step 3 then the errors will likely be an issue as they currently get rendered to a str in the form's get_context. This may need breaking out into a separate function so it can be called when rendering a field.
BoundField
know's about it's associated form (BoundField.Form
)
Change History (9)
comment:1 by , 2 years ago
Component: | Uncategorized → Forms |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → New feature |
comment:2 by , 2 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 2 years ago
I think this is the logical next/final? step in the form
I think so.
@skidipap -- How are you getting on with this. I had made a tentative start, but then realised you have claimed the ticket and therefore wanted to avoid duplicate work. Maybe if you have some work to share I could help with comments on a PR?
comment:4 by , 2 years ago
Owner: | changed from | to
---|
comment:5 by , 21 months ago
Has patch: | set |
---|---|
Patch needs improvement: | set |
comment:7 by , 20 months ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
follow-up: 9 comment:8 by , 20 months ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
In cad376f8:
comment:9 by , 20 months ago
Many thanks to all who made this possible. Now I can add my CSS classes to my field label tags or at least try 😅
Yes, thanks David. I think this is the logical next/final? step in the form rendering adjustments. +1