It's not clear this is the same problem, as you have only one form in a 
component, and the other component doesn't appear to save to the session. 
Read through the thread to repeat the diagnostics and see if you really are 
observing the same behavior (which implies the second component is saving 
something to the session). If so, the workaround is to have the parent 
action save some dummy data to the session in order to create a session 
file (which will be locked on the subsequent Ajax requests, preventing the 
race condition). If you have your sessions in the database or in cookies, 
then your out of luck, as they cannot be locked.

Anthony

On Monday, July 13, 2015 at 10:25:15 AM UTC-4, 黄祥 wrote:
>
> i face the same situation, already use the formname and clear session. the 
> form must submit twice to get it work.
> e.g.
> *controllers/default.py*
> def sale_order():
>     return locals()
>
> def sale_order_form():
>     form = SQLFORM.factory(
>         Field('product', 'reference product', 
>               requires = IS_IN_DB(db((db.product.quantity > 0) ), 
>                                   db.product.id, db.product._format) ),
>         Field('quantity', 'integer', requires = IS_NOT_EMPTY() ), 
>         )
>     if form.process(formname = 'myform1').accepted:
>         response.flash = T('Form accepted')
>         
>         id = int(request.vars.product)
>         
>         row = db(db.product.id == id).select().first()
>         
>         quantity = int(request.vars.quantity)
>         price = int(row.selling_price)
>         session.sale_order[id] = quantity, price
>         
>         response.js =  "jQuery('#sale_order_checkout').get(0).reload()"
>     elif form.errors:
>         response.flash = T('Form has errors')
>     return dict(form = form)
>
> def sale_order_checkout():
>     link_callback = 'sale_order_callback'
>     link_empty = 'sale_order_empty'
>     return dict(session_detail = session.sale_order, link_callback = 
> link_callback, 
>                 link_empty = link_empty)
>
> *views/default/sale_order.html*
> {{extend 'layout.html'}}
>
> {{=LOAD('default', 'sale_order_form.load', ajax = True, 
>         target = 'sale_order_form') }}
>
> {{=LOAD('default', 'sale_order_checkout.load', ajax = True, 
>         target = 'sale_order_checkout') }}
>
> *views/default/sale_order_form.load*
> {{=form}}
>
> any idea how to face this?
>
> thanks and best regards,
> stifan
>
> On Tuesday, April 23, 2013 at 7:09:51 PM UTC+7, Anthony wrote:
>>
>>
>> What to do about this? I suppose one option would be to always create a 
>>>> new session file when a new session is started, even if the session is 
>>>> empty on the first request of the session (in the above example, an empty 
>>>> session file would be created on accessing the index page). Some apps 
>>>> never 
>>>> use the session, though, and would therefore have a bunch of unnecessary 
>>>> session files (though I suppose you could still use the global settings to 
>>>> turn off sessions).
>>>>
>>>
>>> turning to the old system makes me "sick & sad" . Creating a session 
>>> only when it's needed is "the right thing to do"© .
>>>
>>
>> The above suggestion isn't quite going back to the old system. In the old 
>> system, the session file was created on the first request (of a new browser 
>> session) *and* re-written on every request (even if it didn't change) -- 
>> the latter was more a source of inefficiency than the former. The above 
>> suggestion would return to creating the session file on the first request, 
>> but it would not re-write the session on every request. Anyway, I'm not 
>> saying we should necessarily take this approach, just spelling out the 
>> issues and options.
>>  
>>
>>> Another option is to leave it up to the developer to save something to 
>>>> the session in the parent page request when the page contains multiple 
>>>> Ajax 
>>>> requests that will be accessing the session. Maybe we could provide a 
>>>> convenience method for this, such as session.save(), which would force 
>>>> saving the file even if the session is empty (such a method might have 
>>>> other uses, such as saving and then unlocking a session in the middle of a 
>>>> request).
>>>>
>>>
>>> wouldn't a simple note in the book close the deal ?
>>>
>>
>> Saving dummy data to the session feels like a hack, so I think a new 
>> method like session.save() would be nice.
>>  
>>
>>> I think there's a bigger problem with sessions in cookies and the db -- 
>>>> they aren't locked at all, so you can get race conditions with them even 
>>>> once the session has initially been saved.
>>>>
>>>> it's a problem "in general": either you want concurrency or you want 
>>> locking..... can we even theoretically solve that problem ? I don't think 
>>> so. 
>>>
>>
>> I think with sessions we generally want locking (or at least the option 
>> to lock) -- in order to avoid race conditions (presumably that's why 
>> locking the file-based sessions was implemented to begin with). When 
>> storing sessions in the db, the table definition does include a "locked" 
>> field, but it is not used -- there is this commented line in 
>> session.connect():
>>
>> # rows[0].update_record(locked=True)
>>
>> Maybe that can be used. Not sure what to do about cookie-based sessions.
>>
>> More generally, maybe we could allow more control over session locking by 
>> adding a "lock" argument to session.connect(). Those who want to take 
>> advantage of the option could globally disable automatic sessions and 
>> manually open the session via session.connect() in the app (choosing 
>> whether to do so with or without locking, depending on whether it matters 
>> for the particular action).
>>
>> Anthony
>>
>>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to