Next installment :-/  (As a reminder, the objective is to create an
SQLFORM in the controller that can be used to validate/update using
request.vars from a separate custom form.  The problem was how to
include the required formkey and formkey value in the custom form.)

Please note the changes described below are not intended as "this is
how it should be" but is really part of trying to understand how all
the bits fit.

i) In the controller, set a boolean attribute on SQLFORM namely
"customview"

ii) added a hiddenxml() method to FORM that outputs just the hidden
input controls not the whole form - basically a subset of xml()

iii) added an xml() method to SQLFORM:
if self.customview and customview==True:
  return FORM.hiddenxm(self)
else:
  return FORM.xml(self)

In my view, if it is not a custom form I just include {{=form}} and in
the controller form=SQLFORM(db.recipe).  If I am using a custom form
then
in the view I include {{=form}} within my <form> and in the controller
add form.customview=True.

This appears to work, i.e. in the customview=True case I just get the
hidden fields included:
<input value="036227189211" type="hidden" name="_formkey" /><input
value="recipe" type="hidden" name="_formname" />

BUT... when the form is submitted and the formkeys are checked they
never match.  It is more confusing because as I step thru the code
(EasyEclipse/PyDev) the formkeys in the session are constantly
changing.  Can anyone suggest what I am missing?

Bill

On Oct 10, 9:04 pm, billf <[EMAIL PROTECTED]> wrote:
> The problem I have is that when recipe=None, =form.record.any_field
> fails hence the thinking that a "new" record containing defaults would
> overcome this.  I have had a stab with the following:
>
> class SQLROW(SQLStorage):
>     """
>     Return a row created from the table definition with values set to
> defaults.
>     A row is represented as an SQLStorage object.
>     """
>     def __init__(self,table):
>         for fieldname in table.fields:
>             field=table[fieldname]
>             value=field.default
>             if fieldname=='id':
>                 value=0
>             if value==None:
>                 value=''
>             self[fieldname]=value
>
> usage: record=SQLROW(db.recipe)  That may not fit into the web2py way
> of naming but it's just an experiment :-)
>
> My next problem is that to utilise the SQLFORM created in the
> controller to allows accepts() and all the nice auto validation and db
> updating, I believe my custom form in the view needs to contain 2
> hidden fields holding the key and value of the form (to check with the
> session).  As far as I can see, these are generated when {{=form}} is
> processed in the view, stored in the session and output in the
> response.  The underlying values are not accessible from the form,
> e.g. =form.formkey - which is a shame.  I am looking at how to call a
> function on the SQLFORM from the view where the function would
> generate just the part of xml() that generates the key/values, updates
> the session and returns the input type="hidden" tags.  An alternative
> might be to set an indicator on the SQLFORM that is checked by xml()
> to output all the form or just the hidden subset.  Any thought greatly
> welcomed.
>
> Bill
>
> On Oct 10, 3:28 pm, mdipierro <[EMAIL PROTECTED]> wrote:
>
> > OK just replace
>
> > recipe=recipes[0]
>
> > with
>
> > recipe=recipes[0] if recipes else None
>
> > On Oct 10, 5:57 am, billf <[EMAIL PROTECTED]> wrote:
>
> > > I have gone down the route of using the following controller code
> > > (I've left out a few checks for simplicity)
>
> > > recipes=db(db.recipe.id==id).select()
> > > recipe=recipes[0]
> > > form=SQLFORM(db.recipe, recipe)
> > > return dict(form=form)
>
> > > ... and in the view
>
> > > <form name="{{=form.formname}}" method="post"
> > > action="controller_name">
> > > <input type="hidden" name="id" value="{{=form.record.id}}">
>
> > > <label>Name:</label><input type="text" name="{{=form.formname}}_name"
> > > size="50" maxlength="50" value="{{=form.record.name}}"/>
> > > etc.
>
> > > This seems to work well BUT I want to use the same view for insert and
> > > update and when inserting there is no record!  It would be great to be
> > > able to call a function that creates an recipe record with id=0 and
> > > all fields set to default values.  It must be quite simple by
> > > iterating through the columns of the table definition but I don't
> > > really know enough yet to just code it.  More importantly does the
> > > function already exist?  I don't want to rely on cloning an existing
> > > instance.
>
> > > Bill
>
> > > On Oct 10, 5:08 am, mdipierro <[EMAIL PROTECTED]> wrote:
>
> > > > form is the form, form[0] is the table inside it. form[0][0] is the
> > > > first row. form[0][-1] is the last row, etc.
> > > > You can do
>
> > > >     form[0].append(TR('Label',TAG.button('whatever'),'comment'))
>
> > > > You can add more attributes to your TAG.button
>
> > > > On Oct 9, 8:39 pm, Jose de Oliveira Filho <[EMAIL PROTECTED]>
> > > > wrote:
>
> > > > > Thanks a bunch, Massimo. I completely overlooked the "hidden" thing
> > > > > in the FORM source, but the first answer is what I was looking for.
>
> > > > > I need to add an extra button to a SQLFORM, like "Save and Add
> > > > > another". I could put it outside the form but it looks really bad,
> > > > > any recommendations here ?
>
> > > > > By the way, did you ever think of turning the SQLFORM generation into
> > > > > divs instead of a table ?
>
> > > > > Thanks again,
>
> > > > > Deodoro Filho
>
> > > > > Em 09/10/2008, às 18:04, mdipierro escreveu:
>
> > > > > > Good questions. Answers below.
>
> > > > > >> (in controller:)
> > > > > >> def new_project():
> > > > > >>    f = FORM(INPUT(_name = "project_title", _type = "text"))
> > > > > >>    if f.accepts(request.vars, session):
> > > > > >>       db.project.insert(dict(title = f.vars.title, description =
> > > > > >> f.vars.description, user = session.user_id))
> > > > > >>       redirect(URL(r = request, f = "list"))
> > > > > >>    else:
> > > > > >>       return dict(form = f)
>
> > > > > >> My question is: is there some way of doing:
> > > > > >> ...db.insert.project(f.vars)...
> > > > > >> ?
>
> > > > > >> I'd be awesome if I could make "user" a hidden field directly.
> > > > > >> That'd be like:
>
> > > > > >> ...f = SQLFORM(db.project, hidden = [db.project.user])
> > > > > >>    f.vars.user = session.user_id...
>
> > > > > >> and then remove the db.project.insert line.
>
> > > > > > There are many ways you can do it:
>
> > > > > > 1) the recommended way
>
> > > > > >      # list only the fields you want and pass the others directly to
> > > > > > the vars
> > > > > >      f=SQLFORM(db.project,fields=['title'])
> > > > > >      f.vars.user=session.user_id
>
> > > > > > 2) use a hidden field
>
> > > > > > f=SQLFORM(db.project,fields=['title'],hidden=dict
> > > > > > (user=session.user_id))
> > > > > >      #but now the visitor can tamper with the hidden field in the 
> > > > > > form
>
> > > > > > 3) Manually using
>
> > > > > >     ## vars has to be a dictionary (like form.vars) and must only
> > > > > > contain valid fields, not including id.
> > > > > >     vars=form.vars
> > > > > >     vars.user=session.user_id
> > > > > >     db.project.insert(**vars)
> > > > > >     ## the ** unpacks the dictionary into named arguments
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"web2py Web Framework" group.
To post to this group, send email to web2py@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/web2py?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to