I have some code that basically does:
self.data = session['cart']
and then later:
self.data['some-key'] = 'some-value'
This always used to update the session, but now it doesn't. If I change my code to be as follows:
self.data['some-key'] = 'some-value'
session.modified = True
It suddenly works again.
We can't detect when values change within a session, only when they are replaced. Could you pinpoint when this behavior change occured? I don't think it should have ever worked.
the code works as expected, he removed the part that made werkzeug check for modification and left the part that didn't
@RonnyPfannschmidt As far as I can see no line of code was removed, only the last one was added.
@untitaker It worked in 10.2 but not in 11.0
Are you sure you didn't simple have some code that marked the session as modified (e.g. by assigning/removing another item)?
I'm sure - I copied the code from another project that used flask 10.2 and it didn't work. After a couple of hours trying to figure out what I'd broken, I realised what was going on and downgraded from flask 11.1 to 10.2 and it worked again.
All of my session handling code in about 15 projects works in the same way as the snippet above. It's obviously possible to work around this, but ideally I'd like to avoid having to refactor all of my session handling or keeping Flask back to version 10.2.
The actual code that is broken looks like this (some irrelevant stuff stripped out):
class CartSession(object):
def __init__(self):
if KEY_CART not in session:
session[KEY_CART] = {}
self.data = session[KEY_CART]
@property
def items(self):
item_list = self.data.get(KEY_ITEMS, [])
return [CartItem.from_dict(i) for i in item_list]
def add_item(self, quantity, product, option):
if KEY_ITEMS not in self.data:
self.data[KEY_ITEMS] = []
# This appends a dict to the list
self.data[KEY_ITEMS].append(CartItem(quantity, product.id, option).to_dict())
To be clear: calling add_item(...) no longer updates the session unless I set session.modified to True afterwards.
self.data[KEY_ITEMS] = [] is the only case that marks the session as modified. Since you have a plain list there there is absolutely no way for Flask to detect changes within that list...
If it works for you in 0.10.2 then I'd add some debug code to the flask session code to see what triggers the modification. The easiest way to do so would be adding import traceback; traceback.print_stack() inside on_update in SecureCookieSession in flask/sessions.py.
@ThiefMaster I understand the theory, but it has always worked in the past. As I said, downgrading to Flask 10.2 did fix the issue.
If it's only this case where I'm modifying a list inside the session that is broken, it's actually not a big deal. I was worried that it would have broken all of my session handling code.
Either way - thanks for your help. I understand what's going on a lot better now!
This is the first instance where something has suddenly stopped working after updating Flask. I was actually beginning to think I'd lost the plot!
Is it good practice to manually do a session.modified = True?
When you change mutable objects inside your session: yes.
When you just assign/remove something there's no need to do so.
Oh, the reason for the changing behavior is quite simple: 0.10 simply sets the cookie all the time. See https://github.com/pallets/flask/commit/d1d835c02302884b2db1cab099b3ea6a84f41d32
I didn't immediately realize this because the relevant commit is three years old.
Ok - I'll work around it. Thanks for all of your help. I'll just set the config variable to save the session each time as it's not much of an overhead.
Most helpful comment
Ok - I'll work around it. Thanks for all of your help. I'll just set the config variable to save the session each time as it's not much of an overhead.