#34077: Make BoundField renderable.
-----------------------------------------+------------------------
               Reporter:  David Smith    |          Owner:  nobody
                   Type:  Uncategorized  |         Status:  new
              Component:  Uncategorized  |        Version:  4.1
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 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.

 1. [https://github.com/django/django/blob/main/django/forms/fields.py#L82
 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")
 }}}

 2. Add a new method, either as a filter or as a new method to
 
[https://github.com/django/django/blob/d795259ea96004df0a2469246229a146307bcd2c/django/forms/boundfield.py#L14
 BoundField] which renders the `BoundField` with it's fields template
 (`boundfield.field.template_name`)

 3. Consider if we need to provide a default implementation of this. If so
 we should replicate the `div.html` templates. Specifically
 
[https://github.com/django/django/blob/d795259ea96004df0a2469246229a146307bcd2c/django/forms/templates/django/forms/div.html#L5-L21
 these lines]. The `div.html` template can be updated to use this new
 method.

 4. 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
 
[https://github.com/django/django/blob/d795259ea96004df0a2469246229a146307bcd2c/django/forms/forms.py#L328-L348
 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`)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34077>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070183b6d1cf8b-0c26d7d6-2b32-46e9-8025-3a566ab3adec-000000%40eu-central-1.amazonses.com.

Reply via email to