Massimo

Thanks for your answers.

> 1) About SQLROWS below. I am not sure what it is supposed to do.
> SQLFORM(table,None) should already pre-populate the form with default
> values from table.field.default.

I asked the question Oct 10 11.57am "does a function already exist?"
but didn't get this answer so I had a go myself.  When I try your
suggestion though, the default values are ONLY in
form.table.field.default.  form.record is None.  If I use
form.table.field.default in my custom form there are 2 problems:
i) it doesn't reflect user input so next time through the form is back
to displaying defaults
ii) defaults are not set implicitly, i.e. a string without a
default='' is None

This doesn't really give me what I want.  If I go back to my solution
of creating a record containing defaults I now realise that I have
another problem:

If my custom form uses form.record.some_attribute it is is ok first
time thru - it has defaults - but after user input it is still just
the original values.
If my custom form uses form.vars.some_attribute then first time thru
it is empty but after user input it reflects the user input.
Conclusion:  there are 2 ways to get the latest value of a form
attribute:
i) merge table.default and vars - although I am not sure that it is as
simple as that, or
ii) extract the value from components (which is in effect the result
of i) as done by accepts()) - I think this is best approach

So I really have 2 problems: i) a consistent source of the latest form
values and ii) formkeys - although this can be avoided by omitting the
session from accepts().  My current thinking is that if a custom view
is being used then SQLFORM should be able to create a visible dict of
latest values (including formkey values) that can be accessed via
=form.latest.my_attribute or similar.

This has the added plus that form.record isn't required so Massimo's
SQLFORM(db.recipe, None) is ok and my SQLROW is redundant - hurrah!

Should this be done in accepts() along with creating the formkeys (see
3) below or when form is serialized {{=form}}?  It is probably more
efficient to do it in accepts() or more specifically postprocessing()
as that is where the component is updated I think.

> > 2) formname is in form.formname and defined in SQLFORM(formname='bla
> > bla')

I have no problem getting formname.  That is set whether formname='bla
bla' or not.

> > 3) formkey is in session._formkey but only AFTER the form is
> > serialized {{=form}} so it is not there if you have a custom form. You
> > have some options:
>
> > a) make your own key session['_formkey[%s]' % 
> > form.formname]=str(uuid.uuid4()) and place it
> > in the form.
>
I could do this but my attempts wanted to use the existing formkey
code.  Anyway, a long-term solution would not want this in all
controllers so it would end up in FORM or SQLFORM anyway(?)

> > b) do not pass "session" to "accepts" so that formkey will not be
> > used.

I guess the check vs session is there for a good reason so any
acceptable solution should support it.

> later post) perhaps this variable should be set when the form is accepted, not
> when serialized....

As I said in an earlier post, I had sussed this and as long as I
wanted to use the existing formkey code I had to modify the xml()
behaviour (actually bypass it) to avoid getting the whole form back.
Should the variable be set in accepts() - see last bit of 1) above.

Bill

On Oct 10, 11:35 pm, mdipierro <[EMAIL PROTECTED]> wrote:
> correction... formkey goes in
>
> session['_formkey[%s]' % form.formname]
>
> perhaps this variable should be set when the form is accepted, not
> when serialized....
>
> Massimo
>
> On Oct 10, 5:31 pm, mdipierro <[EMAIL PROTECTED]> wrote:
>
> > 1) About SQLROWS below. I am not sure what it is supposed to do.
> > SQLFORM(table,None) should already pre-populate the form with default
> > values from table.field.default.
>
> > 2) formname is in form.formname and defined in SQLFORM(formname='bla
> > bla')
>
> > 3) formkey is in session._formkey but only AFTER the form is
> > serialized {{=form}} so it is not there if you have a custom form. You
> > have some options:
>
> > a) make your own key session._formkey=str(uuid.uuid4()) and place it
> > in the form.
>
> > b) do not pass "session" to "accepts" so that formkey will not be
> > used.
>
> > Massimo
>
> > On Oct 10, 3: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 [email protected]
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