Custom Form layout best practice

15 views
Skip to first unread message

Keith R. Fieldhouse

unread,
Feb 26, 2006, 12:26:14 PM2/26/06
to turbo...@googlegroups.com

I'm trying to figure out the "right" way to go about creating custom
form layouts.

I have a form that will show up in a couple of different places in my
application. As it happens, the layouts provideed by TableForm or
ListForm aren't really what I want (developer's suffer from Bike Shed
momements too :-)).

It seems like the correct thing to do is to create a new FormWidget with
a custom template. Within that template though, what is a the right way
to get a hand on each of the fields in my form? The existing forms
widgets simple iterate over "fields" and drop them where the next field
goes. If I want to put *this* field *there*, and *that* field *over
there* how do I get it? It seems like I might be able to use the
field_for() method of Form but I don't know how to get at it within my
form's template?

Or, should I just dispense with the Form widget all together and simply
create .KID files with my layouts.

This is all with the current .9

Thanks for any insigt and apoligies if this is a hopelessly naive
question...

Keith

Jorge Godoy

unread,
Feb 26, 2006, 12:41:04 PM2/26/06
to turbo...@googlegroups.com
"Keith R. Fieldhouse" <turbo...@rexmere.com> writes:

> It seems like the correct thing to do is to create a new FormWidget with
> a custom template. Within that template though, what is a the right way
> to get a hand on each of the fields in my form? The existing forms
> widgets simple iterate over "fields" and drop them where the next field
> goes. If I want to put *this* field *there*, and *that* field *over
> there* how do I get it? It seems like I might be able to use the
> field_for() method of Form but I don't know how to get at it within my
> form's template?

I'm trying three approaches: one is to hand code the form, then simply replace
values and names and ids there, the other is to use widgets inside this custom
template and the last one is to mix both.

As you can imagine, the first one is the less reusable and the one that is
harder to do. The second is the least flexible one since I only gain the
placement control. The third looks like the best approach since it allows me
to use HTML where I need more flexibility and still count on using widgets
where I can.

> Or, should I just dispense with the Form widget all together and simply
> create .KID files with my layouts.

Hmmm... It is another design choice... You can create .kid files and still
subclass some widget to use its methods.


--
Jorge Godoy <jgo...@gmail.com>

Alberto

unread,
Feb 26, 2006, 1:23:29 PM2/26/06
to TurboGears
Hi Keith,

Right now this cannot be done, I think it should but just didn't get on
time ;)

This patch:


Index: turbogears/widgets/forms.py
===================================================================
--- turbogears/widgets/forms.py (revision 852)
+++ turbogears/widgets/forms.py (working copy)
@@ -541,6 +541,8 @@
d['hidden_fields'] = hidden_fields
d['submit'] = self.widgets['submit']
d["submit_text"] = d.get("submit_text", None)
+ d["field_for"] = self.field_for
+ d["error_for"] = lambda name: d["form_errors"].get(name)
return d

Should allow you to do something like this:

class MyForm(widgets.Form):
template = """
<form xmlns:py="http://purl.org/kid/ns#"
name="${name}"
py:attrs="form_attrs"
>
<table border="0">
<tr>
<td>${field_for("name").display()}</td>
<td>${field_for("age").display()}</td>
</tr>
<tr>
<td>${error_for("name")}</td>
<td>${error_for("age")}</td>
</tr>
</table>
</form>
"""

If you don't feel like patching you can achive the same thing by:

class MyForm(widgets.Form):
def update_data(self, d):
super(MyForm, slef).update_data(d)
d["field_for"] = self.field_for
d["error_for"] = lambda name: d["form_errors"].get(name)

and using this as a super class for any form you want to use field_for
and error_for in the template.

There's still work to do regarding the field label and help_text, but
should be a start. I think something on this line should be desirable
default behaviour and get into the trunk... Opinions?

Hope it helps, Alberto

Alberto

Keith R. Fieldhouse

unread,
Feb 26, 2006, 2:18:59 PM2/26/06
to turbo...@googlegroups.com
Alberto wrote:

>Hi Keith,
>
>Right now this cannot be done, I think it should but just didn't get on
>time ;)
>
>This patch:
>
>

Aha. I was starting to look at someting like that and decided I was
missing something. I 'm really glad to see this patch both becuase it
lets me do what I want and it's confirmation that I really was beginning
to "get" the way widgets work.

I agree that something like this should be generally possible. In my
experience, form layout ("can you put this next to this...") is one of
the classic bike sheds in web development. It'll be nice to be able to
keep everthing associted with a form's structure encapsulated in one
place in my code...

Thanks for the quick responses...

Best,

Keith

Michele Cella

unread,
Feb 26, 2006, 6:46:47 PM2/26/06
to TurboGears
Keith R. Fieldhouse wrote:
>
> Aha. I was starting to look at someting like that and decided I was
> missing something. I 'm really glad to see this patch both becuase it
> lets me do what I want and it's confirmation that I really was beginning
> to "get" the way widgets work.
>
> I agree that something like this should be generally possible. In my
> experience, form layout ("can you put this next to this...") is one of
> the classic bike sheds in web development. It'll be nice to be able to
> keep everthing associted with a form's structure encapsulated in one
> place in my code...

IMHO putting "field_for" in the template scope of a form widget doesn't
make much sense since you can use it "only" if you know the form
structure (fields names) before doing the template and that's not the
use case of a form widget, OTOH I can't see any arm in putting it
there.

You can also do something like this if what you need is just
encapsulating the layout:

class FormFields(WidgetsDeclaration):
name = TextField()
age = TextField()

MyFormLayout(Widget):
template_vars = ['form']
template = """
<p py:content="form.field_for(name)"
"""

then:

form = Form(fields=FormFields())
form_layouted = MyFormLayout(form)

and use @validate(form).

Keep in mind that I haven't tested this.

Ciao
Michele

Jorge Vargas

unread,
Feb 26, 2006, 9:58:00 PM2/26/06
to turbo...@googlegroups.com
that sounds like layouts of Swing/AWT Java code.

Max Ischenko

unread,
Feb 27, 2006, 10:02:29 AM2/27/06
to TurboGears
> There's still work to do regarding the field label and help_text, but
> should be a start. I think something on this line should be desirable
> default behaviour and get into the trunk... Opinions?

I think the patch can be included in the trunk. At least, I would make
use of this new feature.

Alberto

unread,
Feb 27, 2006, 1:55:01 PM2/27/06
to TurboGears
I've opened a ticket to discuss if and how we should implement this.
http://trac.turbogears.org/turbogears/ticket/626

Alberto

Dennis Backhaus

unread,
Jul 19, 2013, 12:17:25 PM7/19/13
to turbo...@googlegroups.com
what ever happened to this ticket?

Christoph Zwerschke

unread,
Jul 19, 2013, 1:10:56 PM7/19/13
to turbo...@googlegroups.com
That ticket was about TurboGears 1 widgets, which are not developed any
more; it has been closed 7 years ago (you can still see it at
http://trac.turbogears.org/ticket/626). TurboGears 2 uses ToscaWidgets.

-- Christoph
> <http://trac.turbogears.org/turbogears/ticket/626>
>
> Alberto
Reply all
Reply to author
Forward
0 new messages