OverIQ.com

Sessions in Flask

Last updated on July 27, 2020


Session is yet another way to store user-specific data between requests. It works similar to cookies. To use session you must set the secret key first. The session object of the flask package is used to set and get session data. The session object works like a dictionary but it can also keep track modifications.

When we use sessions the data is stored in the browser as a cookie. The cookie used to store session data is known session cookie. However, unlike an ordinary cookie, Flask Cryptographically signs the session cookie. It means that anyone can view the contents of the cookie, but can't modify the cookie unless he has the secret key used to sign the cookie. That's why it is recommended to set a long and hard to guess string as a secret key. Once the session cookie is set, every subsequent request to the server verifies the authenticity of the cookie by unsigning it using the same secret key. If Flask fails to unsign the cookie then its content is discarded and a new session cookie is sent to the browser.

If you have worked with sessions in languages like PHP, Sessions in Flask is a little different. In PHP, session cookie doesn't store session data instead it only stores a session id. The session id is a unique string PHP creates to associate session data with the cookie. The session data itself is stored on the server in a file. Upon receiving a request from the client, PHP uses the session id to retrieve session data and makes it available in your code. This type of sessions is known as server-side sessions and type of sessions Flask provides by default is known as client-side sessions.

By default, there isn't much difference between cookies and client-based sessions in Flask. As a result, the client-based sessions suffer from the same drawbacks the cookies have like:

  • Can't store sensitive data like passwords.
  • Additional payload on every request.
  • Can't store data more than 4KB.
  • Limit on the number of cookie per website and so on.

The only real difference between cookies and the client-based session is that Flask guarantees that the contents of the session cookie is not tempered by the user (unless he has the secret key).

If you want to use server-side sessions in Flask, you can either write your own session interface or use extensions like Flask-Session and Flask-KVSession.

How to Read, Write and Delete Session data #

The following listing demonstrates how we can read, write and delete session data. Open main2.py file and add the following code just after the article() view function:

flask_app/main2.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from flask import Flask, render_template, request, redirect, \
url_for, flash, make_response, session)
#...
@app.route('/visits-counter/')
def visits():
    if 'visits' in session:
        session['visits'] = session.get('visits') + 1  # reading and updating session data
    else:
        session['visits'] = 1 # setting session data
    return "Total visits: {}".format(session.get('visits'))

@app.route('/delete-visits/')
def delete_visits():
    session.pop('visits', None) # delete visits
    return 'Visits deleted'
#...

Notice that we are using session object just like an ordinary dictionary. Start the server if not already running and visit http://localhost:5000/visits-counter/. You should see total visit count like this:

Refresh the page several times more to increase the visit count.

Flask sends the session cookie to the client only when you create a new session or modify an existing session. When you visit http://localhost:5000/visits-counter/ page for the first time, the body of the else block is executed in the visits() view function and creates a new session. As we are creating a new session, Flask sends the session cookie to the client. The subsequent requests to http://localhost:5000/visits-counter/ execute the code in the if block where are updating the value of visits counter in the session. Modifying a session means that a new cookie needs to be created that's why Flask again sends the new session cookie to the client.

To delete the session data visit http://localhost:5000/delete-visits/.

If you now visit http://localhost:5000/visits-counter/, the visit counter will again start from 1.

By default, session cookie lasts until the browser is closed. To prolong the life of the session cookie set permanent attribute of the session object to True. When permanent is set to True the session cookie will last for permanent_session_lifetime. The permanent_session_lifetime is a datetime.timedelta attribute of Flask object, its default value is 31 days. We can change that by specifying a new value to permanent_session_lifetime attribute or by setting PERMANENT_SESSION_LIFETIME configuration key.

1
2
3
4
5
import datetime

app = Flask(__name__)
app.permanent_session_lifetime = datetime.timedelta(days=365)
# app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=365) # you can also do this

Just like the request object, the session object is also available in the templates.

Modifying Session Data #

Note: Before following along delete all the cookies set by the localhost.

Most of the time session object automatically picks up modifications on it. However, there are some occasions, like modifications on mutable data structures are not picked up automatically. For such cases, you have to set modified attribute of the session object to True. If you don't set modified attribute to True Flask will not send the updated session cookie to the client. The following listing demonstrates how to use modified attribute of the session object. Open main2.py file and add the following code just before the delete_visits() view function.

flask_app/main2.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#...
@app.route('/session/')
def updating_session():
    res = str(session.items())

    cart_item = {'pineapples': '10', 'apples': '20', 'mangoes': '30'}
    if 'cart_item' in session:
        session['cart_item']['pineapples'] = '100'
        session.modified = True
    else:
        session['cart_item'] = cart_item

    return res
#...

The first time you visit http://localhost:5000/session/ the code in the else block is executed and creates a new session where session data is a dictionary. The subsequent request to http://localhost:5000/session/ updates the session data by setting pineapples count to 100. In the next line, we are setting modified attribute to True because without it Flask will not send the updated session cookie to the client.

Start the server if not already running and visit http://localhost:5000/session/. You will be displayed an empty session dictionary because browser had no session cookie to send to the server:

Reload the page again and you will be displayed session dictionary with 10 pineapples as follows:

Reload the page for the third time and you will see session dictionary with 100 pineapples instead of 10 as follows:

The session object has picked up this modification because of the modified attribute. We can verify this by deleting the session cookie and commenting out the line which sets the modified attribute to True. Now after the first request you will always be displayed session dictionary with 10 pineapples.

This completes all you need to know about sessions in Flask. And don't forget by default sessions in Flask are client-side sessions.