0

I have a sample which looks quite like the one in the web2py-docs:

http://web2py.com/books/default/chapter/29/07/forms-and-validators#onvalidation

models/db.py:

db.define_table('numbers',
    # Field('user_id', 'reference auth_user'),
    Field('user_id', 'integer'),
    Field('b', 'boolean'),
    Field('c', 'integer')

# db.numbers.user_id.requires = IS_IN_DB(db, db.auth_user.id)
db.numbers.user_id.writable = db.numbers.user_id.readable = False
db.numbers.id.writable = db.numbers.id.readable = False

controllers/default.py:

def my_form_processing(form):
    if not form.vars.b:
       form.vars.c = None

# @auth.requires_login()   
def insert_numbers():
   # record = db(db.numbers.user_id==auth.user_id).select().first()
   record = db(db.numbers.user_id=1).select().first()
   db.numbers.c.show_if = (db.numbers.b == True)
   form = SQLFORM(db.numbers, record)
   if form.process(onvalidation=my_form_processing).accepted:
       session.flash = 'record inserted'
       redirect(URL())
   return dict(form=form)

but added some "magic":

  • In my original code the form requires you to be logged in and always loads the record with the user_id == auth_id. To simplify things the record for user_id==1 is always loaded.
  • If checkbox 'b' is not checked, hide field 'c' (see: Conditional fields)
  • If checkbox 'b' is not checked and the form is submitted, clear value 'c' (see: onvalidation)
  • FTR: if the record does not exist it will be INSERTed, if it already exists it will be UPDATEd. (web2py-magic).

This works quite well (the database-value of c is set to NULL if the 'b' is false) but here is the catch:

  • Check 'b' (field 'c' is shown) and enter a value in 'c' and submit the form. (b = True and c = $value in database) -> Fine.
  • The form is shown again with a checked 'b' and $value in 'c' -> Fine again.
  • Uncheck 'b' (field 'c' will get hidden) and submit the form. (b = False and c = Null in database (because of onvalidation=my_form_processing)) -> Fine too!
  • The form is shown again with an unchecked 'b' only but if you check 'b' again field 'c' has still $value in it (instead of an empty field).

How can I clear the form-value of field 'c'? (If I just reload the page while 'b' is False, 'c' will be an empty field. This problem only occurs on submit).

Can somebody help me with this?

dpat
  • 253
  • 3
  • 9
  • After checking my sample code with my real code I just figured out that the _redirect(URL())_ line was missing all the time. Now it works. Thanks everyone! – dpat Nov 19 '15 at 20:08

1 Answers1

0

If your goal is to simply conditionally delete that variable, one way to do it would be the following:

def insert_numbers():
   record = db(db.numbers.user_id=1).select().first()
   db.numbers.c.show_if = (db.numbers.b == True)
   form = SQLFORM(db.numbers, record)

   if form.validate(message_onsuccess = 'record inserted'):
       if not form.vars.b:
          del form.vars.c
       db['numbers'].insert(**form.vars)
       db.commit()   # just to be safe
       redirect( URL(...) )
   return dict(form=form)
Boa
  • 2,609
  • 1
  • 23
  • 38
  • Hmm... After the change from _form.process()_ to _form.validate()_ (with _db[].insert_) the database is not getting updated. Did I miss something? – dpat Nov 19 '15 at 20:06
  • @dpat - Made some edits that should fix it. I'm guessing it was the 'next' param within 'validate()' that was screwing things up. – Boa Nov 19 '15 at 22:27