Hi Gregor,

On the way home from DjangoCon I realized there is a (IMHO) elegant solution to this problem that is closer to the nature of django's template language.

What you want with form-rendering is having defaults, but being able to override them; which is something you can do with django's templates. I think something like the following would be conceptually nice:

# in some template
    {% with my_form as form %}
      {% include 'my_app/my_form.html' %}
    {% endwith %}

# in templates/my_app/my_form.html
    {% extends 'form_as_table.html' %}
    {% block fieldblock %}
      {% ifequal field.name 'unnecessary_field' %}
        {# don't use this field #}
      {% else %}
        {{ block.super }}
      {% endifequal %}
    {% endblock %}

# in templates/form_as_table.html
    {% block form %}
      {% block formerrors %}
        ...{# formerrors rendered #}
      {% endblock %}
      {% block fields %}
        {% for field in form.fields %}
          {% block field %}
            <tr>
<th>{% block label %}...{# label rendered #}{% endblock %}</th>
              <td>
{% block fielderrors %}...{# fielderrors rendered #} {% endblock %} {% block widget %}...{# widged rendered #}{% endblock %}
              </td>
            </tr>
          {% endblock %}
        {% endfor %}
      {% endblock %}
    {% endblock %}

Now this is not ideal in a few ways; as far as I can see:
1) the form rendering has to be done in a separate file, because inheritance is needed
2) it would be more elegant if every field-block would have its own name

Django's template language could be extended a little bit (?) to improve this: 1) block inheritance -- like a template can extend another template, a block could be able to extend another block or template:
    {% block form %}
      {% extends 'partial.html' %}{# or extendsblock block.super #}
    {% endblock form %}
2) dynamic block names -- like a template name in an {% extends %} tag can be either a string or a variable, the same could hold for the block name in a {% block %} tag (backward compatibility would have to be solved somehow; different tag name/extra argument/...).

This would result in something like (for removing a field):

    {% with my_form as form %}
      {% block form %}
        {% extends 'form_as_table.html' %}
        {% dynamically_named_block 'unnecessary_field' %}
          {# overrides the field with nothing #}
        {% enddynamically_named_block %}
      {% endblock %}
    {% endwith %}

Note that also the unnecessary_field-block can extend its base block.

Choosing exactly which fields to render could be done like this:

    {% with my_form as form %}
      {% block form %}
        {% extends 'form_as_table.html' %}
        {% block fields %}
          {% for field_name in 'field1 field2 field3'|split %}
            {% dynamically_named_block field_name %}
{{ block.super }}{# refers to the dynamically_named_block #}
            {% enddynamically_named_block %}
          {% endfor %}
        {% endblock fields %}
      {% endblock %}
    {% endwith %}

Just brainstorming... let me know what you think.

Cheers, Roald


On Jun 3, 2011, at 4:58 PM, Gregor Müllegger wrote:

Hi,

this is the second RFC regarding template form rendering API/syntax. The first one defined how a complete form or a subset of fields will be rendered. I'm now proposing more tags to render more details like only the label of a form
field.

Currently we haven't discussed how we will substitute what we currently do
with using::

{{ form.non_field_errors }}
{{ form.errors }}
{{ form.field.errors }}
{{ form.field.help_text }}
{{ form.field.label_tag }}


We will implement these with template tags that are aware of the currently
used layout:

Substituting {{ \*.errors }}::

{% formerrors <form instance|field instance|any ErrorList/ErrorDict> %}

Some examples:
Display *all* errors of a form::
{% formerrors my_form %} (equals current {{ my_form.errors }})

Non-field errors::
{% formerrors my_form.non_field_errors %} equals {{ my_form.non_field_errors }}

Single-field errors::
{% formerrors my_form.firstname %} equals {{ my_form.firstname.errors }}

Basically it will render the error list/dict that is available in the *errors*
attribute of the passed in object. As an alternative (e.g. the
non_field_errors) you can pass in directly a error list that gets rendered::

{% formerrors my_custom_error_list %}
{% formerrors my_form.field.errors %}


Substituting ``{{ form.field.label_tag }}``

This one might be pretty obvious::
{% formlabel my_form.field %}


Substituting {{ form.field.help_text }}

Also pretty obvious::
{% formhelp my_form.field %}

But the naming is IMO not ideal. {% helptext %} as alternative is reasonable, but Carl and I agreed on that we wanted the tag to start with form* but
{% formhelptext %} is to long. So we settled on {% formhelp %}
Better suggestions are welcome.


That's it basically. I don't see any controversies in here, but as usual
with a RFC: comments are requested and will be integrated. :-)


--
Servus,
Gregor Müllegger

--
You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com . To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/django-developers?hl=en .


--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to