Thanks Massimo (and Jonathan),

I think the complexity is not so much of a problem.  As you noted, it works
very well.   It's just that it does so much that a bit more explanation is
needed so new users can understand how it works.

I'd be in favor of putting your detailed description (plus a bit of
explanation about how the controller gets called twice) in the Forms and
Validation chapter, somewhere near the sentence that begins "The full
signature of the accepts method is the following:"

Cheers,
Mike


On Thu, Sep 16, 2010 at 1:26 PM, mdipierro <mdipie...@cs.depaul.edu> wrote:

> assuming form=SQLFORM(db.table,record_id)
>
>
> form.accepts(request.vars,session,formname='xxx',hideerror=False,dbio=True)
>
> does the following
> 1) if not request.vars._formname=='xxx' then form is not being self
> submitted, generate a CSRF-prevention security key and store it in
> session, return False
> 2) if not request.vars._formkey==CSRF-key-in-session, this is a double
> form submission or a a CSRF attack, return False
> 3) use the depth first tree traversal algorithm to find all the INPUT,
> SELECT and TEXTAREA objects in the form, check if they have a
> corresponding entry in request.vars and validate it accordingly. If it
> does not pass validation store the error in form.errors[fieldname] and
> modify the form by injecting error messages in it (unless
> hideerror=True). When validating each INPUT object, all validators are
> executed in order, if one passes, it filters request.vars.fieldname
> into form.vars.fieldname
> 4) for SQFORMS if dbio==True (default) and there are no form.errors it
> does a db.table.insert(**form.vars) or
> db(db.table.id==record_id).update(**form.vars) depending on whether
> this is a create for or an update form (determined by the presence of
> the record_id in form definition). If this is a create form, the id
> returned by insert is stored in form.vars.id
> 5) If here and no errors return True
>
> This is a nutshell. It is a bit more complicated because it needs to
> deal with the odd behavior of select and checkboxes vs text input,
> repeated fields names, the presence of Widgets which may override the
> field validators and the way errors are to be displayed.
>
> SQLFORM.accepts calls FORM.accepts (very similar to each other) are
> the most complex piece of code in web2py. Not the one I am most happy
> with. If I were to re-do it I would redo it differently (in particular
> because of how widgets are dealt with) but the API is clean and it
> works well.
>
> Massimo
>
> On Sep 16, 12:08 pm, Michael Ellis <michael.f.el...@gmail.com> wrote:
> > Thanks, Jonathan.  That's approximately what I had reasoned it must be
> > doing, but couldn't state as clearly as you have.
> >
> > So, if I'm now understanding it correctly, form.accepts() is roughly
> > equivalent to the following conditions:
> >
> > (request contains submitted form elements) and
> > (form key matches) and
> > (all elements pass validation)
> >
> > The 'magic' is simply that clicking the submit button sends a second
> request
> > to the controller that created it. So the form object only *seems* to
> > persist;  in actuality, it's recreated from scratch when the second
> request
> > comes in.
> >
> > All of which explains why I was unable to store extra info in the form
> > object at view time and have it available after form.accepts() came back
> > True.
> >
> > Is that a fair summary of how it works?
> >
> > On Thu, Sep 16, 2010 at 11:04 AM, Jonathan Lundell <jlund...@pobox.com
> >wrote:
> >
> > > On Sep 16, 2010, at 7:26 AM, Michael Ellis wrote:
> >
> > > > I was never much bothered by either of those issues, but there is one
> > > > bit of 'magic' that did (and to some extent still does) confuse me.
> > > > I'm wondering if it might be worthwhile to give an detailed
> > > > explanation what goes on in form.accepts().
> >
> > > > When I first saw the idiom
> >
> > > >   if form.accepts():
> > > >      ...
> > > >   return dict(form=form)
> >
> > > > my assumption was that the call to form.accepts() was somehow
> > > > rendering and transmitting the page and waiting for a user response.
> > > > But then, I wondered how that could be since the form isn't passed to
> > > > the view until the return() is executed.  Then I tried tracing a
> > > > controller and saw that it was being called multiple times.  I got
> > > > lost down in the gluon code and more or less gave up trying to find
> > > > out exactly how the rabbit gets into the hat. Now I just use it and
> > > > trust that it works, but it still bothers me not to know what's going
> > > > on under the hood.
> >
> > > I've had the same reaction. The key to my understanding form.accepts,
> fwiw,
> > > was reading accepts itself. Keep in mind that web2py encourages form
> > > self-submission. That implies that the same code (controller/function)
> > > typically needs to run twice: once to create the page+form for display,
> and
> > > again to handle the form's submission.
> >
> > > So form.accepts() is telling you whether it's the first time through,
> form
> > > creation (False) or the second, form submission (True). It's a little
> more
> > > complicated than that because of validation and error handling, but
> that's
> > > it in a nutshell.
> >
> >
>

Reply via email to