IMPORTANT: Bill's patch

4 views
Skip to first unread message

mdipierro

unread,
Nov 9, 2008, 7:42:26 PM11/9/08
to web2py Web Framework
Finally I found the time to look into Bill's patch for custom forms.

I like the idea a lot but for a number of reasons, independently on
this patch, I had to change/improve the source code of gluon/html.py.

I made lots of small changes for gluon/html.py!

I put the patch-in compatibly with the latest changes. This means if
something is messed up it is my fault, not Bill's fault.

1) Please test that your existing forms (FORM, SQLFORM) work with the
latest trunk (mdipierro/devel).

2) custom forms now work like this:

<form>
<input name="field" value="{{=form.latest.field}}" />
{{if form.errors.field:}}<div
class="error">{{=form.errors.field}}<div>{{pass}}
<input type="submit" />
<!-- insert hidden fields to avoid double-submission! //-->
{{for field in form.hidden_fields():}}{{=field}}{{pass}}
</form>

Bill, can you please test that it works well with SELECT, TEXTAREAs,
checkboxes and radioboxes?

Massimo

mdipierro

unread,
Nov 9, 2008, 7:54:04 PM11/9/08
to web2py Web Framework
IGNORE this email.... I am going to run more tests myself first...
Will get back to you...

DenesL

unread,
Nov 9, 2008, 11:30:32 PM11/9/08
to web2py Web Framework
Regarding this subject, I have been running some tests as time
permits.
May I suggest the following (which I might have mentioned before):

1) The form needs to be more CSS friendly (following the MVC pattern).
This means no tables.
In my tests I have been able to trim the fields to: <label...>
+<input...>+comment+<br/>
and with very simple CSS make the form look like the current one.
More complex CSS could be used to position each element individually
if desired.

2) For each field passed to the form its label and its value must be
accessible in the view via a statement similar to the one mentioned
above: {{=form.latest.field}}, mine look like {{=form.label.field}}
and {{=form.value.field}}. Labels are required for translation
purposes. Some field values, like those of select type fields, require
special consideration; specially when the fields can be converted to
display only (e.g. using DIV instead of INPUT).

3) Custom forms also need custom form error handling. My solution so
far is to use a small JS to change the background color of the fields
in error and change the title attribute to hold the error, so hovering
a field in error displays the error message. But this is probably a
matter of personal preference. Same as replacing the comment with an
image of a question mark that opens the text when requested without
cluttering the form.

4) In the future I would like to integrate the automatic creation of
cascaded fields and autocompletes if possible.

I could be leaving something out but things tend to come out on the
ensuing discussion.

mdipierro

unread,
Nov 9, 2008, 11:39:13 PM11/9/08
to web2py Web Framework
fine with everything but what's the problem of table in form. You can
use CSS to completely override the table layout and more the TD
anywhere you like on the screen as if they were a DIV. Am I wrong?

Massimo

billf

unread,
Nov 10, 2008, 1:06:24 AM11/10/08
to web2py Web Framework
1) tables over something else: it does seem to be a subject of great
discussion that people get very energised about. But I guess that if
you take out tables then someone else will object :-) Isn't the idea
of custom forms that if you want labels you code your own view?

2) labels: personally I don't think the specification of labels fits
elegantly in the model or the controller but I recognise the need to
put them somewhere if you want to avoid duplicating them in multiple
views. Ideally, they could be defined in an application view, e.g.
layout.html, and referenced by views that extend that - is that
possible? I would interested to hear other people's views.

3) I think custom error handling is part of custom views: the
developer has access to the field value and error messages so can do
what they want.

4) Sounds great: once spec'd it will be interesting to see if these
are core web2py or not.

My original proposal grew out of my own requirements to convert an
existing app to web2py: I just wanted access to the latest values and/
or html component (to handle SELECTs). As such the proposal works
fine.

However, since then, I have got interested in (IMHO) cleaning up the
web2py approach to MVC. By that I mean, no view stuff in the model
(e.g. labels) or the controller (passing labels to SQLFORM) and
separating db updates from html creation (both in SQLFORM). So I have
been developing some ideas that are probably at the point where group
comment would be really useful. I would post them as a blueprint but
this forum seems to be the place to get feedback so I am going to
create a new thread.

mdipierro

unread,
Nov 10, 2008, 2:01:57 AM11/10/08
to web2py Web Framework
Attention!!! I posted in trunk a complete rewrite of gluon/html.py

In my tests it does not break anything but please try it and let me
know if it break something before I post an new web2py version.

The reason for the rewrite is mainly to make form processing twice as
fast and the code more readable, but also to include Bill's patch in a
more elegant way. The new html is 5% smaller than the previous one.

About the comments below:

1) I agree with Bill
2) one can do db.table[fieldname].label and get the label (*)
3) I agree. One can do {{if form.errors.has_key(fieldname):}}
{{=form.errors[fieldname}}{{pass}} (*)
4) Now you can do a custom form like

db.define_table('person',SQLField('name'))

def index():
form=SQLFORM(db.person)
if form.accepts(request.vars,session)
return dict(form=form)

{{if form.errors:}}{{=form.errors}}{{pass}}
<form>
<input type="text" name='name' value="{{=form.values.name}}" />
<input type="submit" />
{{=form.hidden_fields()}} <!--you need this to prevent double
submission and allow multiple forms //-->
</form>

Please let me know if it works. I am hoping to post a new release
before my talk at pyworks2008.

Massimo

mdipierro

unread,
Nov 10, 2008, 2:07:24 AM11/10/08
to web2py Web Framework
(*) means this is not a feature. Has always been there.

DenesL

unread,
Nov 10, 2008, 9:54:04 AM11/10/08
to web2py Web Framework
I will have to go over the changes in html.py but:
1) I also agree with Bill. The point here was really the MVC
separation as he calls it in a separate post. Plus a leaner version of
the generated HTML. I have no idea how hard would it be to re-position
a TD in a complex form just using CSS.
2) Many debatable positions can be taken here too. Should labels be
considered part of the form data or not? Where would they fit better?
<add your own here >
I know the info is available from other sources but I think it is more
elegant to have it all come from one source: the form itself.
2b) A separate issue here is the use of display only fields versus the
current all input. The presentation value becomes dependent on its
final use (input or display), and the existence of: record, reference,
requires and widgets for each. Again, the objective would be to have
it all available from one source: the form.
3) Errors have been always available from the form object, the way it
should be IMO. Here I want to hear about other nice and elegant ways
to handle the errors. Maybe we can have one in the improved version if
the opinions are not too divergent.
4) I have cascades and autocompletes in my current forms and I posted
how I did it, but the setup is a little convoluted so I would like to
automate it. They use jQuery plugins. Other special field types that
can be added here? Maybe make them into web2py plugins?.
It is all a work in progress...

ceej

unread,
Nov 16, 2008, 8:25:02 PM11/16/08
to web2py Web Framework
Using your example Massimo:

db.define_table('person',SQLField('name'))

def index():
form=SQLFORM(db.person)
if form.accepts(request.vars,session)
return dict(form=form)

{{if form.errors:}}{{=form.errors}}{{pass}}
<form>
<input type="text" name='name' value="{{=form.values.name}}" />
<input type="submit" />
{{=form.hidden_fields()}} <!--you need this to prevent double
submission and allow multiple forms //-->
</form>

Could i do:

<form>
{{if form.errors.name:}}<div
class="error">{{=form.errors.name}}<div>{{pass}}
<input type="text" name='name' value="{{=form.values.name}}" />
<input type="submit" />
{{=form.hidden_fields()}} <!--you need this to prevent double
submission and allow multiple forms //-->
</form>

So I could put the errors next to the field instead of all to together
at the top, I know you said you could on your second post but then you
said you were changing it, so I wanted to know if you still can. I've
already written a helper for this but if it's now built In I will use
that :)

On Nov 10, 6:54 am, DenesL <denes1...@yahoo.ca> wrote:
> I will have to go over the changes in html.py but:
> 1) I also agree with Bill. The point here was really the MVC
> separation as he calls it in a separate post. Plus a leaner version of
> the generated HTML. I have no idea how hard would it be to re-position
> a TD in a complex form just using CSS.
> 2) Many debatable positions can be taken here too. Should labels be
> considered part of the form data or not? Where would they fit better?
> <add your own here >
> I know the info is available from other sources but I think it is more
> elegant to have it all come from one source: the form itself.
> 2b) A separate issue here is the use of display only fields versus the
> current all input. The presentation value becomes dependent on its
> final use (input or display), and the existence of: record, reference,
> requires and widgets for each. Again, the objective would be to have
> it all available from one source: the form.
> 3) Errors have been always available from the form object, the way it
> should be IMO. Here I want to hear about other nice and elegant ways
> to handle the errors. Maybe we can have one in the improved version if
> the opinions are not too divergent.
> 4) I have cascades and autocompletes in my currentformsand I posted
> how I did it, but the setup is a little convoluted so I would like to
> automate it. They use jQuery plugins. Other special field types that
> can be added here? Maybe make them into web2py plugins?.
> It is all a work in progress...
>
> On Nov 10, 2:01 am, mdipierro <mdipie...@cs.depaul.edu> wrote:
>
> > Attention!!! I posted in trunk a complete rewrite of gluon/html.py
>
> > In my tests it does not break anything but please try it and let me
> > know if it break something before I post an new web2py version.
>
> > The reason for the rewrite is mainly to make form processing twice as
> > fast and the code more readable, but also to include Bill's patch in a
> > more elegant way. The new html is 5% smaller than the previous one.
>
> > About the comments below:
>
> > 1) I agree with Bill
> > 2) one can do db.table[fieldname].label and get the label (*)
> > 3) I agree. One can do {{if form.errors.has_key(fieldname):}}
> > {{=form.errors[fieldname}}{{pass}} (*)
> > 4) Now you can do acustomform like
>
> > db.define_table('person',SQLField('name'))
>
> > def index():
> >     form=SQLFORM(db.person)
> >     if form.accepts(request.vars,session)
> >     return dict(form=form)
>
> > {{if form.errors:}}{{=form.errors}}{{pass}}
> > <form>
> > <input type="text" name='name' value="{{=form.values.name}}" />
> > <input type="submit" />
> > {{=form.hidden_fields()}} <!--you need this to prevent double
> > submission and allow multipleforms//-->
> > </form>
>
> > Please let me know if it works. I am hoping to post a new release
> > before my talk at pyworks2008.
>
> > Massimo
>
> > On Nov 10, 12:06 am, billf <billferr...@blueyonder.co.uk> wrote:
>
> > > 1) tables over something else:  it does seem to be a subject of great
> > > discussion that people get very energised about.  But I guess that if
> > > you take out tables then someone else will object :-)  Isn't the idea
> > > ofcustomformsthat if you want labels you code your own view?
>
> > > 2) labels: personally I don't think the specification of labels fits
> > > elegantly in the model or the controller but I recognise the need to
> > > put them somewhere if you want to avoid duplicating them in multiple
> > > views.  Ideally, they could be defined in an application view, e.g.
> > > layout.html, and referenced by views that extend that - is that
> > > possible?  I would interested to hear other people's views.
>
> > > 3) I thinkcustomerror handling is part ofcustomviews: the
> > > > > 3)Customformsalso needcustomform error handling. My solution so

ceej

unread,
Nov 16, 2008, 8:30:15 PM11/16/08
to web2py Web Framework
This was my helper:

class form_helper(object):

def error(self,form,error_name,div_class='form_error'):
if request.vars.has_key('name') and form.errors.has_key
(error_name):
response.write(XML('<div class="%(class)s">%(error)s</
div>'%{'error': form.errors[error_name],'class': div_class}))

def value(self,form_value):
if request.vars.has_key('name') and not
response.message_sent:
response.write(request.vars[form_value])

Then In my view i can just do:

<form method="post" action="" class="contact">
{{form.error(contact_form,'name')}}
<label>your name</label>
<input name="name" type="text" id="contactname" value="{{form.value
('name')}}"/>
<input name="submit" type="submit" class="submit" id="submit"
value="submit" title="Signup" />
</form>

ceej

unread,
Nov 20, 2008, 1:17:15 PM11/20/08
to web2py Web Framework
Hi Massimo,

I've tried:

_update_clip_fields=[
'title',
'description',
'tags',
'length'
]
post_save=SQLFORM(db.videos,fields=_update_clip_fields)
if post_save.accepts(post_save,session):
response.flash="Updated Video"
return dict(_video=_video,post_save=post_save)

But I get an error:

Traceback (most recent call last):
File "/Users/blank/Dropbox/Sites/myapp/source/gluon/restricted.py",
line 62, in restricted
exec ccode in environment
File "/Users/blank/Dropbox/Sites/myapp/source/applications/myapp/
controllers/api.py", line 150, in <module>
File "/Users/blank/Dropbox/Sites/myapp/source/gluon/globals.py",
line 55, in <lambda>
self._caller=lambda f: f()
File "/Users/blank/Dropbox/Sites/myapp/source/applications/myapp/
controllers/api.py", line 105, in edit_clip
if post_save.accepts(post_save,session):
File "/Users/blank/Dropbox/Sites/myapp/source/gluon/sqlhtml.py",
line 155, in accepts
raw_vars=dict(vars.items())
AttributeError: 'SQLFORM' object has no attribute 'items'

On Nov 9, 11:01 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> Attention!!! I posted in trunk a complete rewrite of gluon/html.py
>
> In my tests it does not break anything but please try it and let me
> know if it break something before I post an new web2py version.
>
> The reason for the rewrite is mainly to make form processing twice as
> fast and the code more readable, but also to include Bill's patch in a
> more elegant way. The new html is 5% smaller than the previous one.
>
> About the comments below:
>
> 1) I agree with Bill
> 2) one can do db.table[fieldname].label and get the label (*)
> 3) I agree. One can do {{if form.errors.has_key(fieldname):}}
> {{=form.errors[fieldname}}{{pass}} (*)
> 4) Now you can do acustomform like
>
> db.define_table('person',SQLField('name'))
>
> def index():
>     form=SQLFORM(db.person)
>     if form.accepts(request.vars,session)
>     return dict(form=form)
>
> {{if form.errors:}}{{=form.errors}}{{pass}}
> <form>
> <input type="text" name='name' value="{{=form.values.name}}" />
> <input type="submit" />
> {{=form.hidden_fields()}} <!--you need this to prevent double
> submission and allow multipleforms//-->
> </form>
>
> Please let me know if it works. I am hoping to post a new release
> before my talk at pyworks2008.
>
> Massimo
>
> On Nov 10, 12:06 am, billf <billferr...@blueyonder.co.uk> wrote:
>
> > 1) tables over something else:  it does seem to be a subject of great
> > discussion that people get very energised about.  But I guess that if
> > you take out tables then someone else will object :-)  Isn't the idea
> > ofcustomformsthat if you want labels you code your own view?
>
> > 2) labels: personally I don't think the specification of labels fits
> > elegantly in the model or the controller but I recognise the need to
> > put them somewhere if you want to avoid duplicating them in multiple
> > views.  Ideally, they could be defined in an application view, e.g.
> > layout.html, and referenced by views that extend that - is that
> > possible?  I would interested to hear other people's views.
>
> > 3) I thinkcustomerror handling is part ofcustomviews: the
> > > > 3)Customformsalso needcustomform error handling. My solution so

mdipierro

unread,
Nov 20, 2008, 1:20:23 PM11/20/08
to web2py Web Framework
if post_save.accepts(post_save,session):

should be

if post_save.accepts(request.vars,session):

but you know this already.

Massimo

ceej

unread,
Nov 20, 2008, 1:24:23 PM11/20/08
to web2py Web Framework
Massimo, I totally missed that. I've been up to 4am working to get
some of the other projects live. Think I might need to take a nap
lol :)

ceej

unread,
Nov 20, 2008, 1:51:28 PM11/20/08
to web2py Web Framework
Using post_save=SQLFORM(db.videos,_video,fields=_update_clip_fields)
can you not specify just certain fields you would like to update
because I'm getting SyntaxError: user is tampering with form. (_video)
being my records.

ceej

unread,
Nov 20, 2008, 9:32:56 PM11/20/08
to web2py Web Framework
Hey Massimo,

I think for the SQLFORM custom forms you should add <input
type="hidden" value="<field id>" name="id"/> to
{{=post_save.hidden_fields()}} and maybe even a {{=post_save.form_start
()}} {{=post_save.form_end()}} function so it can include the correct
headers like enctype="multipart/form-data" into the form. This would
make make updates with custom forms really easy instead of having to
add those lines yourself.

mdipierro

unread,
Nov 20, 2008, 10:45:55 PM11/20/08
to web2py Web Framework
Yes we should.

Meanwhile I suggest you replace

post_save=SQLFORM(db.videos,_video,fields=_update_clip_fields)

with

post_save=SQLFORM(db.videos,_video,fields=_update_clip_fields+
['id'],showid=False)

Massimo

Peter

unread,
Dec 23, 2008, 4:55:26 PM12/23/08
to web2py Web Framework
This looks like what I need: custom forms with fields that can tie
into model and database, including validation,etc.
But this modified version of "Bill's patch" hasn't yet made it into
production yet (1.54), is that correct?

-Peter


On Nov 10, 8:01 am, mdipierro <mdipie...@cs.depaul.edu> wrote:
> Attention!!! I posted in trunk a complete rewrite of gluon/html.py
>
> In my tests it does not break anything but please try it and let me
> know if it break something before I post an new web2py version.
>
> The reason for the rewrite is mainly to make form processing twice as
> fast and the code more readable, but also to include Bill'spatchin a

Peter

unread,
Dec 23, 2008, 5:58:22 PM12/23/08
to web2py Web Framework
Sorry, please ignore. It seems I missed the new thread on this:
http://groups.google.com/group/web2py/browse_thread/thread/4cd0a75de54f32aa/2c20dbcbd9d8aa9d?lnk=gst&q=custom+forms#2c20dbcbd9d8aa9d

Cheers,
-P

On Dec 23, 10:55 pm, Peter <peter.kleyn...@gmail.com> wrote:
> This looks like what I need:customformswith fields that can tie
> into model and database, including validation,etc.
> But this modified version of "Bill's patch" hasn't yet made it into
> production yet (1.54), is that correct?
>
> -Peter
>
> On Nov 10, 8:01 am, mdipierro <mdipie...@cs.depaul.edu> wrote:
>
> > Attention!!! I posted in trunk a complete rewrite of gluon/html.py
>
> > In my tests it does not break anything but please try it and let me
> > know if it break something before I post an new web2py version.
>
> > The reason for the rewrite is mainly to make form processing twice as
> > fast and the code more readable, but also to include Bill'spatchin a
> > more elegant way. The new html is 5% smaller than the previous one.
>
> > About the comments below:
>
> > 1) I agree with Bill
> > 2) one can do db.table[fieldname].label and get the label (*)
> > 3) I agree. One can do {{if form.errors.has_key(fieldname):}}
> > {{=form.errors[fieldname}}{{pass}} (*)
> > 4) Now you can do acustomform like
>
> > db.define_table('person',SQLField('name'))
>
> > def index():
> >     form=SQLFORM(db.person)
> >     if form.accepts(request.vars,session)
> >     return dict(form=form)
>
> > {{if form.errors:}}{{=form.errors}}{{pass}}
> > <form>
> > <input type="text" name='name' value="{{=form.values.name}}" />
> > <input type="submit" />
> > {{=form.hidden_fields()}} <!--you need this to prevent double
> > submission and allow multipleforms//-->
> > </form>
>
> > Please let me know if it works. I am hoping to post a new release
> > before my talk at pyworks2008.
>
> > Massimo
>
> > On Nov 10, 12:06 am, billf <billferr...@blueyonder.co.uk> wrote:
>
> > > 1) tables over something else:  it does seem to be a subject of great
> > > discussion that people get very energised about.  But I guess that if
> > > you take out tables then someone else will object :-)  Isn't the idea
> > > ofcustomformsthat if you want labels you code your own view?
>
> > > 2) labels: personally I don't think the specification of labels fits
> > > elegantly in the model or the controller but I recognise the need to
> > > put them somewhere if you want to avoid duplicating them in multiple
> > > views.  Ideally, they could be defined in an application view, e.g.
> > > layout.html, and referenced by views that extend that - is that
> > > possible?  I would interested to hear other people's views.
>
> > > 3) I thinkcustomerror handling is part ofcustomviews: the
> > > > > 3)Customformsalso needcustomform error handling. My solution so
Reply all
Reply to author
Forward
0 new messages