I am trying to use the same controller function for insert and update by calling different SQLFORMs depending on existence of arguments passed to the function:
def manage_doc():
db.doc_master.sr_no.readable=False
db.doc_master.sr_no.writable=False
if not len(request.args):
form = SQLFORM(db.doc_master)
else:
doc_to_edit = db.doc_master(request.args[0])
form = SQLFORM(db.doc_master, doc_to_edit)
if form.process(onvalidation=check_form_manage_doc).accepted:
if not len(request.args):
session.flash = 'Document added'
else:
session.flash = 'Document updated'
redirect(URL('index'))
return dict(form=form)
This is the onvalidation callback:
def check_form_manage_doc(form):
new_inward_no = form.vars.inward_no
new_inward_year = form.vars.inward_date.year
if (form.vars.doc_date > form.vars.inward_date):
form.errors.doc_date = 'Document Date cannot be later than Inward Date'
rows = db(db.doc_master.inward_date.year() == new_inward_year)
for row in rows.select():
if ((row.id != form.vars.id) and (row.inward_no == new_inward_no)):
form.errors.inward_no = 'Inward No %s already exists for Doc %s' % (str(new_inward_no), str(form.vars.id))
form.vars.sr_no = str(new_inward_no)+'/'+str(new_inward_year)
While the function is working OK on insertion, on update it fails because form.vars.id
is always None
in the callback function. What is wrong with my code?
form.vars.id
is not populated at the time that onvalidation
is run. You can instead use request.post_vars.id
, which will of course continue to be None
for record creation but will contain the record ID for updates (request.post_vars.id
will be a string, so convert to int
when not None
).
As an aside, note there is no reason to conditionally create two different forms -- you can instead simply do:
form = SQLFORM(db.doc_master, record=request.args(0))
request.args(0)
will simply be None
if there are no URL args. Also, note that the record
argument can simply be the record ID rather than a DAL Row
object containing the record.
Also, note that the .process
method includes some arguments that can further simplify your code -- all of your form code can be replaced with:
form = SQLFORM(db.doc_master, request.args(0)).process(
onvalidation=check_form_manage_doc,
message_onsuccess='Document %s' % ('updated' if request.args else 'added'),
next=URL('index'))