I am trying to understand how to store form data in Flask sessions. I've encountered behavior that seems weird to me when appending data to a session dictionary that has already been defined in a previous request.
I define the following view:
@bp.route("/new-form", methods=("GET", "POST"))
def new_form():
if request.method == "POST":
if not "x" in session:
session["x"] = []
session["x"].append(json.dumps(request.form))
return session.get("x")
return render_template("main/new-form.html")
I would expect session["x"]
to keep its data and append the new json data from the form with every request. However, only the most recent form appended to session["x"]
is ever displayed.
What I really don't understand is that when I add another key to session before appending the form data to session, the form data acts how I would expect, i.e. session["x"]
becomes a long list of each form that is submitted until I clear the data from the session:
if request.method == "POST":
session["idontgetit"] = 1
...
Just adding the line session["idontgetit"] = 1
makes session["x"]
behave how I expected.
I am using the back button on my browser to test this, I don't know if that would have any unexpected effects. It behaves consistently both ways.
When you modify a mutable object (in your case its list) stored in session directly (e.g., session["x"].append(...))
, Flask's session mechanism doesn't detect the change. This happens because Flask only marks the session as "modified" when you explicitly assign a new value to a key in session.
You validated this yourself by testing it using session["idontgetit"] = 1
When you assign a value to session["idontgetit"]
, Flask detects that the session has been modified. This triggers Flask to regenerate the session cookie, which then includes the updated state of session["x"]
To ensure that your changes to session["x"] are saved, you should reassign the modified list back to session["x"] after making changes.
Do something like this
@bp.route("/new-form", methods=("GET", "POST"))
def new_form():
if request.method == "POST":
if "x" not in session:
session["x"] = []
# Modify the list and reassign it
x = session["x"]
x.append(json.dumps(request.form))
session["x"] = x # Reassign to mark the session as modified
return jsonify(session["x"])
return render_template("main/new-form.html")
Based on your flask and python version adding this line session.modified = True
after you append will do the job.