Home - funkybob/django-reformation GitHub Wiki

Reformation

Form rendering belongs in the template. Honestly. As a programmer, I should not be deciding how a form looks to a user. The designers shouldn't have to come bother me any time they want to change an attribute on a field.

So... let's think about this:

  1. All rendering belongs in templates.

    But we should make sure to make it as easy as possible for people to write widget templates.

    So, we provide a ::Template Tags:: lib.

  2. Validate that all fields have been rendered.

    Something raised recently as a security concern is that if your model changes and you're using a ModelForm that just uses excludes= ... you may accidentally have fields appear on your form that you didn't expect.

    When the designer must explicitly render each field, it's possible to raise a warning when not all fields have been rendered.

  3. We should dispense with Widgets, and instead introduce Parsers.

    In fact, a Parser is simply that part of the Widget that knows how to recover the data from the form in accordance with how that particular widget works. Consider the difference between a checkbox, versus radio buttons or a select for implementing a boolean field.

    Currently in django there are very few "parsers" in use:

    • default
    • list (MultiValueDict aware
    • file (and cleanable file)
    • checkbox
    • null boolean select
    • Multi-Widget (*)
    • select date (separate YYYY / MM / DD fields)
  4. When rendering a widget, we need to explode the information about the field into the context.

    So values such as value, help_text, html_name, auto_id, and so on should be at the top of the context.

    We should also allow form authors to override these values when invoking a widget template. Yes, even 'field' and 'form'.

  5. The current forms code indicates someone's not happy with the "has_changed" implementation as it stands.

    Can we find a better solution?

It would be great if we could let the widget authors inform us which Parser we should use. Each Field should have a white-list of Parsers it supports. Since the data will still be passed through regular validation, this should not open a can of worms in security. I'm willing to be proven wrong here.

Name mangling makes it fairly easy to annotate which Parser the widget would like you to use. However, that will probably require something to iterate through the list of Parsers to find the field data.

Another option is to pass a hidden field, but this feels a bit dirty.

Request flow

Widget template support

Ideally, the form author would be able to do something as simple as:

{% field widgetname form.field .... %}

How we handle passing the extra information is tricky. Most of it should just be put straight into the context.

However, there's also a case to be able to pass "attributes" for the widget to place intelligently, such as data-*.

Some ideas for this:

  1. Any kwarg with a "attr:" prefix is collected into an attrs dict for the context.
  2. data_ prefix -- apparently used in CrispyForms
  3. [just thought of this as I was writing it] arbitrary namespace prefix, similar to data: , allowing you to collect any kwargs into dicts.

Currently "formulation" works using a {% form widget_template_name %} block tag to pull in all available widgets, their being the block tags in the referenced template. It was hoped this approach would firstly avoid lots of template loads, and secondly allow widget template authors to keep all their code in once palce.