Temporary changing default values of a Form

924 views
Skip to first unread message

Fabiano - deStilaDo

unread,
Jan 4, 2011, 5:28:06 PM1/4/11
to web2py-users
Hi,

I have a default value for a field defined on the table definition,
along with its validators.

I want to create a form with a different initial value for some
fields, based on the link the user clicked. Something like "add new
item for this category" and the new item form come with that category
pre-filled.

The way I found to do this was:

form = SQLFORM(db.mytable)
form.custom.widget['myfield']['value'] = request.args(0)
form.custom.widget['myfield']._postprocessing()

the _postprocessing() call was necessary in case of multiple options
widget (like Selects), else the selected option wouldn't be updated.

It works fine, but I believe I am messing with the inners of the
object, a bad programming practice, as the internal implementation may
change and break my app.

Is there a proper way of doing this?


Kind regards,

Fabiano.

mdipierro

unread,
Jan 4, 2011, 5:39:11 PM1/4/11
to web2py-users
Excellent question:

db.mytable.myfield.default = request.args(0)
form = SQLFORM(db.mytable)


On Jan 4, 4:28 pm, Fabiano - deStilaDo <fabianoeng...@gmail.com>
wrote:

Kenneth Lundström

unread,
Jan 4, 2011, 5:41:12 PM1/4/11
to web...@googlegroups.com
There is atleast two other ways of doing this in the controller on-the-fly.

Before you create the FORM object you can do:

db.table.field.default = 0 (you temporarly change what you have defined
i models)

or after you have created the FORM but before if form.accepts

form.vars.field = something


Kenneth

Arun K.Rajeevan

unread,
Jan 20, 2011, 2:26:00 PM1/20/11
to web...@googlegroups.com
Does anybody know how to do it for a select box?
Select box is rendered because it's a foreign key that reference another table.

Kenneth Lundström

unread,
Jan 20, 2011, 2:44:38 PM1/20/11
to web...@googlegroups.com
> Does anybody know how to do it for a select box?
> Select box is rendered because it's a foreign key that reference
another table.

After you have created the form but before if form.accepts define your
default.

form = SQLFORM(db.......)

form.vars.type = 'cleaner'

if form.accepts......

This should work.


Kenneth


Luis Goncalves

unread,
Jul 5, 2011, 1:08:31 PM7/5/11
to web...@googlegroups.com
This doesn't seem to work with auth() forms:

form = auth.register()

form.vars.email = 'lu...@vision.caltech.edu'

return dict(form=form)

doesn't show the predefined value for 'email' in a view that renders  {{=form}}

Does anybody know why?

Thanks!!
Luis.

Massimo Di Pierro

unread,
Jul 5, 2011, 1:20:41 PM7/5/11
to web2py-users
Can you explain the logic? Are you trying to override whatever emails
is typed in by the user on registration?

On Jul 5, 12:08 pm, Luis Goncalves <lgoncal...@gmail.com> wrote:
> This doesn't seem to work with auth() forms:
>
> form = auth.register()
>
> form.vars.email = 'l...@vision.caltech.edu'

Anthony

unread,
Jul 5, 2011, 1:23:48 PM7/5/11
to web...@googlegroups.com
I'm not sure you can pre-populate a registration form that way. form.vars.email has to be set after the form is created but before form.accepts is called -- however, auth.register() creates the form and calls form.accepts. Instead, you can pre-populate by manipulating the form DOM directly:
 
form.element(_name='email').update(_value='lu...@vision.caltech.edu')
 
 
Anthony

Luis Goncalves

unread,
Jul 5, 2011, 1:34:18 PM7/5/11
to web...@googlegroups.com
Yes, I am trying to create an 'invitation' only registration,
where the person receives an email with a link (and identifying token),
and on my website I use the token to pre-populate the registration form,
so that the user only has to pick his password.

thx,
Luis.

Luis Goncalves

unread,
Jul 5, 2011, 1:34:50 PM7/5/11
to web...@googlegroups.com
That worked great!!!  Thanks so much, Anthony!!!
L.

Luis Goncalves

unread,
Jul 6, 2011, 12:51:44 AM7/6/11
to web...@googlegroups.com
One more question:

How do I make the pre-populated elements of the form appear read-only (so that they cannot be altered)?

I've tried in the view:

 {{=form.custom.begin}}
      <div>First name: {{=predef.fname}}</div>
      <div>Last name: {{=predef.lname}}</div>
      <div>Email: {{=predef.email}}</div>
      <div>Password: {{=form.custom.widget.password}}</div>
      <div>Verify password: {{=form.custom.widget.password_two}}</div>
      {{=form.custom.submit}}
  {{=form.custom.end}}

but then the elements for which I don't use the widget (to avoid being edited), seem not to be passed with the submit
( the auth.register method did not accept the form as complete )

is there some way to set  an element of a form to be read-only?

Thanks again!
Luis.

Luis Goncalves

unread,
Jul 6, 2011, 2:12:58 AM7/6/11
to web...@googlegroups.com

I found the answer searching through the group posts:

         form.element(_name='email')['_readonly']=True

although this doesn't seem to be documented in the manual,
and even looking through the gluon directory (and grepping for  _readonly ) didn't reveal anything.

Would this have been obvious to someone more proficient with web2py (I've only been using it for about a month)?

thx!

Luis.

Massimo Di Pierro

unread,
Jul 6, 2011, 8:53:25 AM7/6/11
to web2py-users
You would suggest you do this instead

db.table.email.writable=False

in the controller, before defining the form.

Setting the field readonly in the view may still allow a malicious
attacker to tamper with the field value.

Luis Goncalves

unread,
Jul 6, 2011, 2:04:26 PM7/6/11
to web...@googlegroups.com

Good point!

Unfortunately, I am not expert enough to understand how to do this in my case, because I am using the form=auth.register().

Wouldn't I have to do what you suggest inside Auth.register ?

(for an explanation of why I am doing this, see:  https://groups.google.com/forum/#!topic/web2py/O3O6J5FgXjU )


  def user():
 
      if request.args(0)=='register':
         
          db.table_user.email.writable=False # gives error
          form=auth.register()
   
          registrant = db( db.registrant.token == request.vars.token ).select().first()
 
          form.element(_name='email').update(_value=registrant.email)

 
          form.element(_name='email')['_readonly']=True
 
          return dict(form=form)

Thanks!!
Luis.

Massimo Di Pierro

unread,
Jul 6, 2011, 2:07:43 PM7/6/11
to web2py-users
This should do it:

def user():
if request.args(0)=='register':
registrant = db(db.registrant.token ==
request.vars.token).select().first() or redirect(URL('error'))
db.auth_user.email.writable=False # gives error
db.auth_user.email.default=registrant.email
return dict(form=form)

Anthony

unread,
Jul 6, 2011, 2:28:21 PM7/6/11
to web...@googlegroups.com
On Wednesday, July 6, 2011 2:04:26 PM UTC-4, Luis Goncalves wrote:
          db.table_user.email.writable=False # gives error
 
I think this should be db.auth_user, not db.table_user. Note, the name of the auth user table (which defaults to 'auth_user') is stored in auth.settings.table_user_name, so you could also do:
 
db[auth.settings.table_user_name].email.writable=False
 
 
Anthony

Luis Goncalves

unread,
Jul 6, 2011, 2:39:27 PM7/6/11
to web...@googlegroups.com

Both with Massimo's

          auth.settings.table_user.email.default = registrant.email
          auth.settings.table_user.email.writable=False
          
          form=auth.register()

and with your

          db[auth.settings.table_user_name].email.writable=False
          db[auth.settings.table_user_name].email.default=registrant.email
         
          form=auth.register()

I get the error

Exception: Target receiver address not specified

at the line of form=auth.register()


For reference, the entire block (with error handling removed for clarity) is:


  def user():
         
      if request.args(0)=='register':
             
          registrant = db( db.registrant.token == request.vars.token ).select().first()
 
          db[auth.settings.table_user_name].email.writable=False
          db[auth.settings.table_user_name].email.default=registrant.email
         
          form=auth.register()
         
          return dict(form=form)

return dict(form=auth())

Anthony

unread,
Jul 6, 2011, 3:59:36 PM7/6/11
to web...@googlegroups.com
Do you have:
 
auth.settings.registration_requires_verification = True
 
somewhere? If so, remove that line or set it to False. That attempts to send a verification email to the user's email address (which is failing and causing the error), which I assume you don't need given that your registration is via invitation only.
 
Anthony

Luis Goncalves

unread,
Jul 6, 2011, 8:11:14 PM7/6/11
to web...@googlegroups.com
Actually, I still want email verification to happen (because someone else may stumble upon the link and register with a password unknown to the real user).

Nevertheless, I disabled registration verification, and now I get an error deep within  gloun/tools.py
Error occurs after entering password and submitting the form.
(same error with your and Massimo's version of the solution):

  File "/home/ubuntu/web2py/gluon/tools.py", line 1683, in register
user = self.db(table_user[username] == form.vars[username]).select().first()
KeyError: 'email'
Maybe making table_user.email.writable=False  
prevents auth.register() from creating a new table entry for the new user???

Again, for reference, the (essential) code:


def user():

if request.args(0)=='register':

registrant = db( db.registrant.token == request.vars.token ).select().first()

          auth.settings.registration_requires_verification = False


db[auth.settings.table_user_name].email.writable=False
db[auth.settings.table_user_name].email.default=registrant.email

          # this causes same error
# auth.settings.table_user.email.default = registrant.email
# auth.settings.table_user.email.writable=False

Massimo Di Pierro

unread,
Jul 6, 2011, 9:53:36 PM7/6/11
to web2py-users
My example did not have the line:

form=auth.register()

Luis Goncalves

unread,
Jul 6, 2011, 11:04:38 PM7/6/11
to web...@googlegroups.com
I still get the same error:


  File "/home/ubuntu/web2py/gluon/tools.py", line 1683, in register
user = self.db(table_user[username] == form.vars[username]).select().first()
KeyError: 'email'

I don't know if it makes a difference or not, but I'm using emails for login (not a username) -- as is probably clear to you from the above error.

Code is now:


  def user():
     
      if request.args(0)=='register':
     
          registrant = db( db.registrant.token == request.vars.token ).select().first()
 
          auth.settings.table_user.email.default = registrant.email
          auth.settings.table_user.email.writable=False
     
          auth.settings.registration_requires_verification = False
     
      return dict(form=auth())

Massimo Di Pierro

unread,
Jul 6, 2011, 11:17:39 PM7/6/11
to web2py-users
Are you sure your db.registrant has an email?

Luis Goncalves

unread,
Jul 6, 2011, 11:35:02 PM7/6/11
to web...@googlegroups.com

Yes, when I click on the invite and go to the website I get the registration form filled out with email (and name (excluded from my shortened example)) visible and non-editable.

Luis.

—«sent by mobile»—

Luis Goncalves

unread,
Jul 7, 2011, 12:24:11 AM7/7/11
to web...@googlegroups.com
In fact, just to make sure there wasn't something hidden in my app affecting the behavior,
I downloaded a fresh install of web2py,

and get the same error:


  File "/home/pierluigi/web2py/gluon/tools.py", line 1796, in register

user = self.db(table_user[username] == form.vars[username]).select().first()
KeyError: 'email'

Adding just this code to the 'welcome' app:


 def user():                            
      if request.args(0)=='register':
                                              
          auth.settings.table_user.email.default = 'lu...@vision.caltech.edu'
          auth.settings.table_user.email.writable=False  
                                                                             
          auth.settings.registration_requires_verification = False
                                                                    
      return dict(form=auth())       

L.

Massimo Di Pierro

unread,
Jul 7, 2011, 9:24:52 PM7/7/11
to web2py-users
Please open a ticket in google code. If this is a web2py but will fix
asap.

On Jul 6, 11:24 pm, Luis Goncalves <lgoncal...@gmail.com> wrote:
> In fact, just to make sure there wasn't something hidden in my app affecting
> the behavior,
> I downloaded a fresh install of web2py,
>
> and get the same error:
>
>   File "/home/pierluigi/web2py/gluon/tools.py", line 1796, in register
>
>     user = self.db(table_user[username] == form.vars[username]).select().first()
> KeyError: 'email'
>
> Adding just this code to the 'welcome' app:
>
>  def user():
>       if request.args(0)=='register':
>
>           auth.settings.table_user.email.default = 'l...@vision.caltech.edu'
>
>           auth.settings.table_user.email.writable=False
>
>           auth.settings.registration_requires_verification = False
>
>       return dict(form=auth())
>
> L.
>
>
>
>
>
>
>
> On Wed, Jul 6, 2011 at 8:35 PM, Luis Goncalves <lgoncal...@gmail.com> wrote:
> > Yes, when I click on the invite and go to the website I get the
> > registration form filled out with email (and name (excluded from my
> > shortened example)) visible and non-editable.
>
> > Luis.
>
> > —«sent by mobile»—
> > On Jul 6, 2011 8:17 PM, "Massimo Di Pierro" <massimo.dipie...@gmail.com>

Luis Goncalves

unread,
Jul 7, 2011, 9:54:45 PM7/7/11
to web...@googlegroups.com
Done!

Thank you!!!

Luis.
Reply all
Reply to author
Forward
0 new messages