Proposal: Form rendering with filters

153 views
Skip to first unread message

Joseph Kocherhans

unread,
Mar 18, 2008, 5:45:53 PM3/18/08
to django-d...@googlegroups.com
I have been pretty unhappy about the way html has been generated from
newforms for awhile now. I think we've come up with a good design that
makes form rendering a lot easier, and a lot more modular. The basic
idea is to render forms, formsets, errors, etc. with filters. Here are
a few examples:

{% load forms %}

{{ formset|as_ul }} Render the entire formset as a ul
{{ form|as_ul }} Render the entire form as a ul
{{ field|as_li }} Render the given field and label as an li

{{ formset.non_form_errors|as_ul }} Render non_form_errors as a ul
{{ formset.errors|as_ul }} Render errors as a ul
{{ form.errors|as_ul }} Render errors as a ul
{{ field.errors|as_ul }} Render field errors as as ul

The same idea would apply to widgets, and would let the html pedants
*cough* ubernostrum *cough* ;-) have their non-xhtml ways without
adding 2 methods to every single widget.

{{ field.widget|as_html }} Render the widget as html 4
{{ field.widget|as_xhtml }} Render the widget as xhtml

To accomplish this, each widget would get a new attrs() method that
would return a dict that basically consisted of html attributes. (In
practice it will be slightly more complicated than this, especially
for select widgets, but you get the idea). The as_html and as_xhtml
filters will be able to turn the dict into html code.

So how does this work from a backwards compatibility standpoint? For
now, things can be completely backwards compatible. I would like the
as_X methods to be deprecated, but the __unicode__ method would stick
around for those poor souls who are working in our template language.
Of course, they could import the filters and apply them manually (as
tests might often do), but they won't have to. They just don't get to
customize output.

Joseph

Rajeev J Sebastian

unread,
Mar 18, 2008, 5:48:21 PM3/18/08
to django-d...@googlegroups.com
Hi Joseph,

On Wed, Mar 19, 2008 at 3:15 AM, Joseph Kocherhans
<jkoch...@gmail.com> wrote:
>
> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to render forms, formsets, errors, etc. with filters. Here are

This is a good idea. I do something similiar in my app also.

Regards
Rajeev J Sebastian

Ivan Sagalaev

unread,
Mar 18, 2008, 5:54:33 PM3/18/08
to django-d...@googlegroups.com
Joseph Kocherhans wrote:
> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to render forms, formsets, errors, etc. with filters.

+1

(I'm an HTML pedant too :-) )

Jacob Kaplan-Moss

unread,
Mar 18, 2008, 6:03:34 PM3/18/08
to django-d...@googlegroups.com
On Tue, Mar 18, 2008 at 4:45 PM, Joseph Kocherhans
<jkoch...@gmail.com> wrote:
> {% load forms %}

[this is good].

Jacob

Adrian Holovaty

unread,
Mar 18, 2008, 6:10:41 PM3/18/08
to django-d...@googlegroups.com
On Tue, Mar 18, 2008 at 4:45 PM, Joseph Kocherhans
<jkoch...@gmail.com> wrote:
> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to render forms, formsets, errors, etc. with filters.

Love it. For the record, I talked about this with Joseph here in
person -- it's a good improvement.

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com | everyblock.com

Russell Keith-Magee

unread,
Mar 18, 2008, 8:58:37 PM3/18/08
to django-d...@googlegroups.com
On Wed, Mar 19, 2008 at 6:45 AM, Joseph Kocherhans
<jkoch...@gmail.com> wrote:
>
> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to render forms, formsets, errors, etc. with filters. Here are
> a few examples:
>
> {% load forms %}
>
> {{ formset|as_ul }} Render the entire formset as a ul
> {{ form|as_ul }} Render the entire form as a ul
> {{ field|as_li }} Render the given field and label as an li

I seem to remember a similar suggestion being raised in the early days
of newforms, but it got lost in the noise of the initial design
discussions.

Put me down as a +1.

Russ %-)

Simon Willison

unread,
Mar 22, 2008, 8:32:10 AM3/22/08
to Django developers
On Mar 18, 9:45 pm, "Joseph Kocherhans" <jkocherh...@gmail.com> wrote:
> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to render forms, formsets, errors, etc. with filters. Here are
> a few examples:
>
> {% load forms %}
>
> {{ formset|as_ul }} Render the entire formset as a ul
> {{ form|as_ul }} Render the entire form as a ul
> {{ field|as_li }} Render the given field and label as an li

I've been thinking along similar lines recently, but leaning towards
tags rather than filters. One problem with newforms that hasn't been
addressed yet is that it's hard to apply custom attributes to form
fields - in particular class="", but also attributes like tabindex and
accesskey.

Filters can't take extra arguments, but tags can. I was thinking along
these lines:

{% field email class="special" tabindex="3" %}

For the XHTML/HTML problem (which drives me batty, I have a custom {%
filter %} just to get rid of those nasty slashes) I've been thinking
about having a {% doctype %} tag. This would do two things: it would
save you from having to remember doctype strings - just drop {%
doctype html4strict %} or {% doctype xhtml1trans %} at the top of your
page and the tag will output the correct doctype for you. It would
also set a special variable in the template context (I was thinking
_doctype) which template tags that output HTML could use to decide if
they were going to use XHTML or HTML style output tags.

Cheers,

Simon

Rob Hudson

unread,
Mar 22, 2008, 10:55:32 AM3/22/08
to django-d...@googlegroups.com
On Sat, Mar 22, 2008 at 5:32 AM, Simon Willison <si...@simonwillison.net> wrote:
>
> For the XHTML/HTML problem (which drives me batty, I have a custom {%
> filter %} just to get rid of those nasty slashes) I've been thinking
> about having a {% doctype %} tag. This would do two things: it would
> save you from having to remember doctype strings - just drop {%
> doctype html4strict %} or {% doctype xhtml1trans %} at the top of your
> page and the tag will output the correct doctype for you. It would
> also set a special variable in the template context (I was thinking
> _doctype) which template tags that output HTML could use to decide if
> they were going to use XHTML or HTML style output tags.

That's beautiful. I especially like the idea of the doctype "setting"
telling what the tags to do.

I've always thought the idea of a post-processing filter to strip the
slashes wasn't the best approach but the only other way I found was to
make a set of HTML4 widgets, which I've done here:
http://www.djangosnippets.org/snippets/618/

But it's always seemed a bit hackish, especially since I'm having to
copy/paste all of the render() method just to remove the slash. My
fear is that I won't notice if/when the base's render() method
changes.

I'm happy to see this conversation and would be happy to help
implement these ideas once they're hammered down.

-Rob

Will Hardy

unread,
Mar 22, 2008, 11:21:02 AM3/22/08
to django-d...@googlegroups.com
> {% load forms %}
>
> {{ formset|as_ul }} Render the entire formset as a ul
> {{ form|as_ul }} Render the entire form as a ul
> {{ field|as_li }} Render the given field and label as an li

+1 This is very cool

> {% field email class="special" tabindex="3" %}

-0

This would be convenient, but I think a filter is cleaner and more
consistent, e.g.:

{{ field|class:"special"|as_li }}

This would keep it compatible with the original suggest, which I think
is a logical approach. You could make the filter accept either a Field
object or a string, i.e. if "field" is a Field object, then update the
class attribute in the widget, so that it will be there when the
widget is rendered later. If "field" is a HTML (basestring?), then
update the class attribute in the top element. "tabindex" could be
handled as a filter too... of course, a filter for each possible
attribute is not a generic approach, but we don't use that many HTML
attributes for forms and I think another tag would be clutter.

> I've been thinking about having a {% doctype %} tag.

+1 ... I like where that is going

Cheers,

--
Will Hardy

Bryan Veloso

unread,
Mar 22, 2008, 5:55:39 PM3/22/08
to Django developers
> {% load forms %}

> {{ formset|as_ul }} Render the entire formset as a ul
> {{ form|as_ul }} Render the entire form as a ul
> {{ field|as_li }} Render the given field and label as an li

> I've been thinking about having a {% doctype %} tag.

+1 to both. Definitely clean and straightforward.

Mike Axiak

unread,
Mar 22, 2008, 6:09:52 PM3/22/08
to Django developers

On Mar 22, 11:21 am, "Will Hardy" <e.willha...@gmail.com> wrote:
> {{ field|class:"special"|as_li }}
> [...]
> > I've been thinking about having a {% doctype %} tag.
>
I could be uninformed, but as of now template filters cannot access
the context, and so you can't use filter while expecting doctype to do
the right thing. I think this was the main motivation behind Simon
suggesting tags.
That and
{{ email|class:"special"|tabindex:3|as_li }}
requires a lot of tricks to work properly (and isn't even that
readable) whereas
{% field email class="special" tabindex="3" list %}
can work with a lot of special object communication and can do a lot
of really nifty things with the context (like make list default, use
the doctype setting, etc).

Regards,
Mike

Simon Willison

unread,
Mar 22, 2008, 8:31:35 PM3/22/08
to Django developers
On Mar 22, 10:09 pm, Mike Axiak <mcax...@gmail.com> wrote:
> On Mar 22, 11:21 am, "Will Hardy" <e.willha...@gmail.com> wrote:> {{ field|class:"special"|as_li }}
> > [...]
> > > I've been thinking about having a {% doctype %} tag.
>
> I could be uninformed, but as of now template filters cannot access
> the context, and so you can't use filter while expecting doctype to do
> the right thing. I think this was the main motivation behind Simon
> suggesting tags.

It was - but the ability to customise attributes turned out to be a
side effect that was potentially even more useful.

Cheers,

Simon

Rajeev J Sebastian

unread,
Mar 23, 2008, 3:49:34 PM3/23/08
to django-d...@googlegroups.com

Moreover, the use of filters means that the form can now provide a
better interface for us to write our own fitlers, or tags, etc. Sort
of like what they say about UNIX tools ... small tools combined to
make bigger ones.

Regards
Rajeev J Sebastian

David Cramer

unread,
Mar 27, 2008, 10:47:22 PM3/27/08
to Django developers
SmileyChris pointed me here. I wrote up a rant today about newforms
and what I've done to keep it easy (quick) for building forms.
http://www.davidcramer.net/code/111/making-django-newforms-useful.html

Maybe some of those ideas will be of help. Keep in mind, I use Jinja,
so it's got a lot more capability (as far as I can remember).

On Mar 23, 12:49 pm, "Rajeev J Sebastian" <rajeev.sebast...@gmail.com>
wrote:

Brian Beck

unread,
Apr 11, 2008, 4:44:53 PM4/11/08
to Django developers
On Mar 18, 5:45 pm, "Joseph Kocherhans" <jkocherh...@gmail.com> wrote:

> I have been pretty unhappy about the way html has been generated from
> newforms for awhile now. I think we've come up with a good design that
> makes form rendering a lot easier, and a lot more modular. The basic
> idea is to renderforms, formsets, errors, etc. with filters. Here are
> a few examples:
>
> {% load forms %}
> ...

Has anyone started working on this? I don't see a branch, but I'd
love to help out. I've also been writing similar tags and filters for
my form rendering (see [1]). I definitely agree with using tags
instead of filters due to their flexibility. Unlike the current
situation I hope these would render using the, *ahem*, templating
system? You know that thing for HTML generation and such? Then
people can really bust out the customization with their own widget/
label/form templates.

[1]: http://www.djangosnippets.org/snippets/693/

Aral Balkan

unread,
May 21, 2008, 5:30:30 AM5/21/08
to Django developers
Just a quick bump: has there been any progress on this?

Thanks,
Aral

On Apr 11, 9:44 pm, Brian Beck <exo...@gmail.com> wrote:
<snip>
> Has anyone started working on this? I don't see a branch, but I'd
> love to help out. I've also been writing similar tags and filters for
> my form rendering (see [1]).
<snip>
> [1]:http://www.djangosnippets.org/snippets/693/

Rob Hudson

unread,
May 21, 2008, 11:58:44 AM5/21/08
to Django developers
I'd like to know too. I especially liked both of Simon Willison's
ideas of 1) Template tags for form rendering, and 2) Outputting and
setting of a _doctype variable that the template tags use to decide
what kind of HTML to output.

If nobody has officially started anything, could we set up a Google
code project with the hopes of this being included in Django once it's
working and all the kinks are worked out?

-Rob

Joseph Kocherhans

unread,
May 21, 2008, 12:13:42 PM5/21/08
to django-d...@googlegroups.com
On Wed, May 21, 2008 at 4:30 AM, Aral Balkan <aralb...@gmail.com> wrote:
>
> Just a quick bump: has there been any progress on this?

Not really. I started the implementation on the plane ride back from
PyCon, realized that it wouldn't work *quite* the way I'd proposed
(widgets don't have access to form data, only BoundFields do), and
haven't gotten back to it yet.

Joseph

Humphrey

unread,
Jul 9, 2008, 7:54:41 AM7/9/08
to Django developers
Yes! This is exactly what newforms is missing.
It's probably too late to get it in for 1.0 hey :-(
Reply all
Reply to author
Forward
0 new messages