Default representation of a Form

19 views
Skip to first unread message

Ivan Sagalaev

unread,
Nov 30, 2006, 1:53:47 PM11/30/06
to django-d...@googlegroups.com
Hi!

A new Form class' default representation (that is goes out of `print f`)
is an HTML table. For those who cares about that proverbial 'semantics'
thing this looks wrong. From the practical point of view it's also not
very convenient since it (for example) doesn't allow to layout the form
in different ways: labels above widgets, labels to the left of widgets,
labels and widgets in one string etc.

Instead I suggest this default representation:

<p id="p_fieldname">
<label for="id_fielname">Field name</label>
<input ... id="id_fieldname"/>
</p>
...

An ID on <p> is debatable. However from a recent experience of laying
out a site with forms designed in many different ways it helps immensely!


The thing that I'm not sure how to do is display of errors. I'm now
doing it with <em>:

<p>
<label/>
<input/>
<em class="error">...</em>
</p>
...

But something disturbs me about this way. I would be happy to see a
better proposal!

Thanks!

Adrian Holovaty

unread,
Nov 30, 2006, 3:08:27 PM11/30/06
to django-d...@googlegroups.com
On 11/30/06, Ivan Sagalaev <Man...@softwaremaniacs.org> wrote:
> A new Form class' default representation (that is goes out of `print f`)
> is an HTML table. For those who cares about that proverbial 'semantics'
> thing this looks wrong. From the practical point of view it's also not
> very convenient since it (for example) doesn't allow to layout the form
> in different ways: labels above widgets, labels to the left of widgets,
> labels and widgets in one string etc.
>
> Instead I suggest this default representation:
>
> <p id="p_fieldname">
> <label for="id_fielname">Field name</label>
> <input ... id="id_fieldname"/>
> </p>
> ...

Hey Ivan,

Good idea! I think we should definitely add Form.as_p() -- as we
currently have as_table() and as_ul(). As for which of those is used
by default, it doesn't really matter to me; I like the <table> output,
but I can definitely appreciate the argument for using <p>s instead.

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Ivan Sagalaev

unread,
Nov 30, 2006, 5:12:08 PM11/30/06
to django-d...@googlegroups.com
Adrian Holovaty wrote:
> I like the <table> output,
> but I can definitely appreciate the argument for using <p>s instead.

I would say not using tables for layout may count as a good practice
like encouraging clean URLs, proper distinction of GET and POST etc.

Brantley Harris

unread,
Dec 1, 2006, 2:18:08 PM12/1/06
to django-d...@googlegroups.com
Maybe good practice, but not practical. I'd love to not have to use
tables. But practical CSS just isn't there yet. Yes, tables aren't
good for general layout, but they still have their uses, and forms are
a prime example.

On 11/30/06, Ivan Sagalaev <Man...@softwaremaniacs.org> wrote:

Waylan Limberg

unread,
Dec 1, 2006, 2:32:32 PM12/1/06
to django-d...@googlegroups.com
Brantley Harris wrote:
> Maybe good practice, but not practical. I'd love to not have to use
> tables. But practical CSS just isn't there yet. Yes, tables aren't
> good for general layout, but they still have their uses, and forms are
> a prime example.
>
A table's uses generally consist of representing tabular data. A form
could arguably be considered tabular data in many cases, so a table
could potentially be acceptable. That said, other alternatives certainly
need to be considered, and made available.

So count me +1 on adding Form.as_p()
I'm +0 on making it the default.

Ivan Sagalaev

unread,
Dec 1, 2006, 4:44:37 PM12/1/06
to django-d...@googlegroups.com
Brantley Harris wrote:
> Maybe good practice, but not practical. I'd love to not have to use
> tables. But practical CSS just isn't there yet.

Many web sites prove otherwise though :-)

> Yes, tables aren't
> good for general layout, but they still have their uses, and forms are
> a prime example.

I agree that laying out a form with CSS is not a very clean thing. But
it does give you a way to change the layout with just CSS (like moving
labels to the left or to the top of a field). And with tables you can't
do it in practice.

Anyway we aren't fighting for the only one available method just for the
default. And since this preference is a controversial subject I think
this is the thing that should just be ruled by core team or we may argue
this to death :-)

Brantley Harris

unread,
Dec 1, 2006, 6:06:31 PM12/1/06
to django-d...@googlegroups.com
Bah. I wish all the browsers supported "display: table-cell", that
would take care of all of this nonsense.

James Bennett

unread,
Dec 1, 2006, 7:33:22 PM12/1/06
to django-d...@googlegroups.com
On 12/1/06, Ivan Sagalaev <Man...@softwaremaniacs.org> wrote:
> I agree that laying out a form with CSS is not a very clean thing. But
> it does give you a way to change the layout with just CSS (like moving
> labels to the left or to the top of a field). And with tables you can't
> do it in practice.

It can be a pain, but it doesn't have to be. For a while now, I've
been using definition lists to lay out forms (which is arguably an
acceptable use of them, depending on how you want to read the HTML
spec), and I've found that to be about the easiest thing -- the LABEL
element and associated text go into a DT, and the actual form element
goes into a DD.

This has the accidental benefit of degrading gracefully in non-CSS
browsers, since the common representation of a definition list in
those browsers works well for a form.

So maybe an as_dl() method needs to go in?

;)

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

Lakin Wecker

unread,
Dec 4, 2006, 10:33:24 AM12/4/06
to django-d...@googlegroups.com
as_dl() gets a +1 from me.  I've used definition lists for forms and prefer it over tables. :)

Lakin

Lachlan Cannon

unread,
Dec 5, 2006, 6:31:03 AM12/5/06
to django-d...@googlegroups.com
Lakin Wecker wrote:
> as_dl() gets a +1 from me. I've used definition lists for forms and
> prefer it over tables. :)

Maybe there needs to be an easy hook for people to specify their own way of
laying a form out. It seems the as_ methods are gonna keep growing and growing.
--
Lach
Personal: http://illuminosity.net/

Adrian Holovaty

unread,
Dec 5, 2006, 9:35:04 AM12/5/06
to django-d...@googlegroups.com
On 12/5/06, Lachlan Cannon <la...@illuminosity.net> wrote:
> Lakin Wecker wrote:
> > as_dl() gets a +1 from me. I've used definition lists for forms and
> > prefer it over tables. :)
>
> Maybe there needs to be an easy hook for people to specify their own way of
> laying a form out. It seems the as_ methods are gonna keep growing and growing.

That already exists -- you can subclass the Form and add your own methods.

Adrian Holovaty

unread,
Dec 7, 2006, 1:30:52 AM12/7/06
to django-d...@googlegroups.com
On 12/1/06, James Bennett <ubern...@gmail.com> wrote:
> So maybe an as_dl() method needs to go in?

With as_dl(), how would error messages be displayed?

Adrian Holovaty

unread,
Dec 7, 2006, 1:35:59 AM12/7/06
to django-d...@googlegroups.com
On 11/30/06, Ivan Sagalaev <Man...@softwaremaniacs.org> wrote:
> A new Form class' default representation (that is goes out of `print f`)
> is an HTML table. For those who cares about that proverbial 'semantics'
> thing this looks wrong. From the practical point of view it's also not
> very convenient since it (for example) doesn't allow to layout the form
> in different ways: labels above widgets, labels to the left of widgets,
> labels and widgets in one string etc.
>
> Instead I suggest this default representation:
>
> <p id="p_fieldname">
> <label for="id_fielname">Field name</label>
> <input ... id="id_fieldname"/>
> </p>

I've implemented Form.as_p() in [4178]. The differences between my
implementation and your proposal are that I didn't give the <p> an
"id" attribute, and the errors get displayed in a <p> above the <p>,
rather than after the field.

Waylan Limberg

unread,
Dec 7, 2006, 10:39:49 AM12/7/06
to django-d...@googlegroups.com
Adrian, excellent job abstracting the common code into
`Form._html_output()`. Now, anyone can write there own `as_method()`
as a one-liner - with one minor problem...

On 12/7/06, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 12/1/06, James Bennett <ubern...@gmail.com> wrote:
> > So maybe an as_dl() method needs to go in?
>
> With as_dl(), how would error messages be displayed?

I was going to suggest
<dt>label</dt>
<dd>error<dd>
<dd>field<dd>

But looking at the code, the error string is passed in first
regardless of whether `errors_on_separate_row` or not. Perhaps
`_html_output()` should use the optional mapping key for string
substitution [1]. So, for example:

- 93 output.append(normal_row % ((bf_errors, label, bf)))
+ 93 output.append(normal_row % ({ 'error' :
bf_errors, 'label' : label, 'field' : bf}))

Then

as_dl(self):
return
self._html_output(u'<dt>%(label)s</dt>\n<dd>%(error)s</dd>\n
<dd>%(field)s</dd>', u'?????', '</dd>', False)

Hmm, not sure how the top_errors would display here. Maybe someone
else could enlighten us on that.

Anyway, by key mapping string substitution, that would greatly enhance
the flexibility IMHO. It would certainly make creating custom
`as_method()` functions easier/more flexible.

As an alternative, there is also Template strings [2], but key mapping
works fine and (I believe) was in python2.3 (or earlier) while
Template strings were introduced in python2.4.

[1]: http://www.python.org/doc/current/lib/typesseq-strings.html
[2]: http://docs.python.org/lib/node40.html


--
----
Waylan Limberg
way...@gmail.com

Adrian Holovaty

unread,
Dec 7, 2006, 10:51:59 AM12/7/06
to django-d...@googlegroups.com
On 12/7/06, Waylan Limberg <way...@gmail.com> wrote:
> But looking at the code, the error string is passed in first
> regardless of whether `errors_on_separate_row` or not. Perhaps
> `_html_output()` should use the optional mapping key for string
> substitution [1].

Hey, that's a really good suggestion! I've checked in the improvement in [4182].

As for how to display top_errors in as_dl() -- I don't have any great ideas.

Jesper Karsrud

unread,
Dec 10, 2006, 1:30:44 PM12/10/06
to Django developers

How about not wrapping the labels and fields in anything at all? That's
what makes most sense to me. It makes it even easier to style the forms
using CSS, plus it's even more semantic than using lists (being
unordered or definition lists), paragraphs and definately tables. The
output would be plain and simple;

<label for="field_id">Label:</label> <input type="text"
name="field_name" id="field_id">

Anyone agree with this?

Gary Wilson

unread,
Dec 10, 2006, 11:32:55 PM12/10/06
to Django developers
Lachlan Cannon wrote:
> Lakin Wecker wrote:
> > as_dl() gets a +1 from me. I've used definition lists for forms and
> > prefer it over tables. :)
>
> Maybe there needs to be an easy hook for people to specify their own way of
> laying a form out. It seems the as_ methods are gonna keep growing and growing.

+1

What if instead of adding various as_* methods that we have a
FormFormatter class that determines how the form displays. The
_html_output and as_* methods would become FormFormatters. Formatter
could be a parameter to the Form constructor, and could default to the
table formatter like how it is now. This would make Form display with
its FormFormatter similar to a form Field and its Widget.

This might even be something that would make sense as a setting,
default_formformatter. Usually one would not be mixing and matching
more than one formatter for a given site. If I wanted to change the
display of all the forms on my site, I could make the change in one
place instead of having to change all the as_p in my templates to
as_my_p.

Adrian Holovaty

unread,
Dec 11, 2006, 1:34:29 AM12/11/06
to django-d...@googlegroups.com
On 12/10/06, Gary Wilson <gary....@gmail.com> wrote:
> What if instead of adding various as_* methods that we have a
> FormFormatter class that determines how the form displays. The
> _html_output and as_* methods would become FormFormatters. Formatter
> could be a parameter to the Form constructor, and could default to the
> table formatter like how it is now. This would make Form display with
> its FormFormatter similar to a form Field and its Widget.
>
> This might even be something that would make sense as a setting,
> default_formformatter. Usually one would not be mixing and matching
> more than one formatter for a given site. If I wanted to change the
> display of all the forms on my site, I could make the change in one
> place instead of having to change all the as_p in my templates to
> as_my_p.

This is an interesting idea, but I think it's important to remember
the as_p(), as_table() and as_ul() shortcut methods are just
*shortcuts*. There's nothing stopping a developer from writing a
custom method on a Form, nor is there anything stopping a developer
from building the form "by hand" by piecing together the individual
fields.

as_p(), as_table() and as_ul() are just shortcuts for the common
(lazy) case when the developer doesn't want to spend time customizing
a form's display in the template. In my opinion, it would be
overengineering to create a separate framework (e.g., the proposed
FormFormatters) to provide for generic ways of being lazy. Put another
way, if we had a FormFormatter framework, that would encourage people
to use these "generic" form formats rather than giving tender loving
care to the design of each form, which is what I'd rather encourage.

Gábor Farkas

unread,
Dec 11, 2006, 6:00:32 AM12/11/06
to django-d...@googlegroups.com

+1


gabor

Benjamin Slavin

unread,
Dec 11, 2006, 10:50:53 AM12/11/06
to django-d...@googlegroups.com
On 12/11/06, Adrian Holovaty <holo...@gmail.com> wrote:
> This is an interesting idea, but I think it's important to remember
> the as_p(), as_table() and as_ul() shortcut methods are just
> *shortcuts*. There's nothing stopping a developer from writing a
> custom method on a Form, nor is there anything stopping a developer
> from building the form "by hand" by piecing together the individual
> fields.
>
> as_p(), as_table() and as_ul() are just shortcuts for the common
> (lazy) case when the developer doesn't want to spend time customizing
> a form's display in the template. In my opinion, it would be
> overengineering to create a separate framework (e.g., the proposed
> FormFormatters) to provide for generic ways of being lazy. Put another
> way, if we had a FormFormatter framework, that would encourage people
> to use these "generic" form formats rather than giving tender loving
> care to the design of each form, which is what I'd rather encourage.
>

I agree with Adrian on this one. There are few common cases that
Django should handle... the flexibility is already there to allow
non-standard uses.

Reply all
Reply to author
Forward
0 new messages