Flaskのsessionではmutableなオブジェクトの変更は検知されず、変更が反映されない。
例えば以下のコードがそれに該当する。
from flask import Flask, session
app = Flask(__name__)
app.secret_key = b'a'
@app.route('/')
def index():
if not 'mutable' in session:
session['mutable'] = []
session['mutable'].append(1)
return str(session['mutable'])
if __name__ == "__main__":
app.run('localhost', port=80, debug=True)
http://localhost/
にアクセスした時に期待する挙動は[1]
、[1,1]
、[1,1,1]
のようにアクセスするたびに配列に1が追加されていくものだが、実際には1つ目以降の1は追加されていくことはない。
これはバグではなく仕様らしく、公式のドキュメントにも書かれていた。
Be advised that modifications on mutable structures are not picked up automatically, in that situation you have to explicitly set the attribute to True yourself.
(出典)https://flask.palletsprojects.com/en/1.1.x/api/#flask.session.modified
以下Google翻訳
可変構造の変更は自動的に取得されないことに注意してください。そのような状況では、属性を明示的にTrueに設定する必要があります。
変更を反映するには明示的に示す必要がある。
方法は簡単でsession.modified
の値をTrueすれば良い。
from flask import Flask, session
app = Flask(__name__)
app.secret_key = b'a'
@app.route('/')
def index():
if not 'mutable' in session:
session['mutable'] = []
session['mutable'].append(1)
session.modified = True # 変更を明示的に示す
return str(session['mutable'])
if __name__ == "__main__":
app.run('localhost', port=80, debug=True)
http://localhost/
にアクセスすれば期待通りの挙動になっていることが分かる。
ちなみに、オブジェクトの変更のほかに代入などを行っている場合は変更が検知されるためsession.modified = True
を行う必要がなくなる。
from flask import Flask, session
app = Flask(__name__)
app.secret_key = b'a'
@app.route('/')
def index():
if not 'mutable' in session:
session['mutable'] = []
session['mutable'].append(1)
session['hoge'] = 1
print(session.modified) # 変更が検知されているためTrueが出力される
return str(session['mutable'])
if __name__ == "__main__":
app.run('localhost', port=80, debug=True)