For anyone wondering why I've been somewhat quieter than normal... we had guests over the weekend, and...
Today, I checked in the first bit of code for TurboGears' form
generator. (Aside: if you have any thoughts on naming for the forms
package, that'd be good. turbogears.forms seems lame.)
Kevin Dangoor wrote:
> You can instantiate a form like this:
> myform = TableForm(widgets=[
> widgets.TextField("name"),
> widgets.TextField("address"),
> widgets.TextField("age", default=0,
> validator=validators.Int())])
Isn't that just begging to be...
class myform(TableForm):
name = widgets.TextField()
address = widgets.TextField()
age = widgets.TextField(default=0, validator=validators.Int())
What I've experienced is that it (forms generators) quickly degenerate
into a closed loop motor that's sort of hard to customize/change for
unexpected usage scenerios.
I agree with a users comment to keep it simple. Allow a few
applications to be built which will also lead to better case-studies
and docs.
PS: If this is not the sort of inputs that this topic requires please
mention.
> class myform(TableForm):
> name = widgets.TextField()
> address = widgets.TextField()
> age = widgets.TextField(default=0, validator=validators.Int())
Well, it depends on whether you think the name of the field in the form
belongs to the field or the form. I've implemented basic form
generation toolkits both ways, and generally think its cleaner to make
it belong to the form as above (since that reinforces the idea that no
two fields can have the same name), but there are reasons to make it
belong to the field too... for example, turbogears.forms currently uses
the name to create a default label if no other label is provided.
Obviously, you can accomplish whatever you want either way, its just a
question of which is more natural.
I actually like the idea of making the name belong to the form, but
using the dict style interface ( form['name'] = widgets.TextField() ).
Unfortunately, this makes it more awkward to make widgets themselves
part of the form definition, since elements, unlike attributes, aren't
part of class definitions (am I using the right terminology here?).
But I agree that the "widgets=[...]" syntax isn't the most natural,
though I don't know what other tradeoffs might have been involved in
choosing it.
Greg
Have you look at that ?
William
Hi Kevin I posted a demo of how I personally deal with form validation
and stuff on the CherryPy users list:
http://groups.google.com/group/cherrypy-users/browse_thread/thread/6fcd3ac9786bac6a/
It's a very primitive way of dealing with it but it could be somewhat
automated... I'm just waiting a bit more to analyze my usage patterns
of it. As of now I like it because it doesn't get at all in your way
and resembles ASP.NET validation handling even if it currently plays at
a much lower level than their system does. Also it doesn't pretend to
compete with Bicking's FormEncode... I would never dare, it's just the
way I like ;-)
Lorenzo
For my own crud application, I choose to generate kid template (and
checksum) at startup time. Previous templates was erased if the
chechsum of the existing templates (or if no template exists) check the
templates.
Advantages :
* generate templates that could be compiled by Kid
* user could choose to modify the templates, without need to know the
"form/widget" framework, and avoid the blank page syndrome
* user could customize widget for a more global impact and don't need
to edit templates
* user could mixed both customization facilities
About Widget, I use the same approach as Kevin except I use the
argument order instead of declare an explicite array =>
myform = TableForm(widgets.TextField("name"),
widgets.TextField("address"),
widgets.TextField("age", default=0,
validator=validators.Int()))
I also use the 3 parameter "key/fieldname", "validator" only for
widgets used for editing, and "default". I define 2 bases types for
widgets :
* Widget : use to display or edit one field
* WidgetsList : use as composite of Widget or WidgetsList
And for the crud, I define 3 families : edit, view, list
About error handling, I choose the had for every field entry in the
dict, a field names 'field_error_' set by editing widget (default is
None), like this the kid template is simple (%(key)s is replaced by the
key/fieldname):
<tr py:if="%(key)s_error_" colspan="2">
<td class="error" py:content="str(%(key)s_error_)"/>
</tr>
I also define based on the TurboEngine code a controller, and the (3)
automatics WidgetsList generators from SQLObject.
Kevin, If your interested I could send you the "crudgear" draft, and
I'll be happy to help you, like this I could work on my TG application
(night only and often offline) andbe sync with last dev.
> The ideas there are fairly similar. Your code looks a bit like
> FormEncode, but does not do the two-way conversion (to_python,
> from_python). Why did you choose to not use FormEncode?
Actually my validators didn't pretend to be comprehensive... I think
that if I was to validate something like an int I would come up with
something like Ian did. C# being statically typed AFAIK they validate
numeric values with regexes but then, of course the value in the
underlying "business logic" is treated like an int or whatever. ASP.NET
validators are really a no-brainer.
I just rolled my own because even with Groovie's tutorial I couldn't
really figure out how to make stuff work my way.
> Thanks for the link to your example!
You're welcome!
Lorenzo
Greg