How about:
yield_key = 'old_job_yield_%s' % request.args(0)
session[yield_key] = old_job_yield
That way, the session key is unique to the particular job being edited, and
editing another job in a different tab won't overwrite the old_job_yield
associated with this job. That won't protect against the user potentially
editing the _same_ job in two different tabs (though to protect against
that, you could use the SQLFORM detect_record_change argument), but should
be OK for separate jobs. There is still a very small opportunity for a race
condition in between reading the current value of quantity_on_hand and
updating that value, but that would require two edit forms being submitted
nearly simultaneously (actually, I think trunk now includes a feature
allowing you to select a record for update, so it will remain locked until
updated).
A few other issues:
- Should be request.args(0), not request.vars(0) (request.vars is like a
dictionary -- access items with keys, not subscripts).
- Should be form.accepts(request, session), not (session, request) --
though, now, you should use form.process().accepted
- After form acceptance, it's probably better to refer to form.vars
(i.e., the validated values) rather than request.post_vars.
Anthony
On Thursday, October 27, 2011 9:54:21 AM UTC-4, Cliff wrote:
>
> What is the Web2py way of making session variables unique to one
> browser tab? This example illustrates the problem.
>
> Model:
> db.define_table('products', Field('quantity_on_hand', 'integer'))
> db.define_table('jobs', Field('job_yield', 'integer'),
> Field('product_id', db.products))
>
> When a user updates the job_yield field, the jobs controller also
> needs to update quantity on hand in the products table. Usually one
> would use a session variable something like this.
>
> def edit():
> # fetch current job yield
> old_job_yield = db.jobs[request.vars(0)].job_yield
> # save it in a session
> session.old_job_yield= old_job_yield
> ...
> if form.accepts(session,request):
> if request.post_vars.job_yield != session.old_job_yield:
> yield_delta = request.post_vars.job_yield -
> session.old_job_yield
> # assume we magically fetch related product id, then
> old_quantity_on_hand =
> db.products[product_id].quantity_on_hand
> new_quantity_on_hand = old_quantity_on_hand +
> yield_delta
>
> db(db.products.id==product_id).update(quantity_on_hand=new_quantity_on_hand)
>
>
> The problem arises if the user edits a different job in a different
> tab. Because there is only one instance of session.old_job_yield, the
> edit action in the other tab will overwrite it.
>
> What is the Web2py way of handling this problem?
>
> Thanks,
> Cliff Kachinske
>
>