plain.sessions

Database-backed sessions for managing user state across requests.

Overview

Sessions allow you to store and retrieve arbitrary data on a per-visitor basis, using a session key stored in a cookie. You can use sessions as a dictionary-like object that automatically handles persistence to the database.

Basic usage

In views that inherit from SessionView, you can use self.session like a standard Python dictionary:

from plain.sessions.views import SessionView

class MyView(SessionView):
    def get(self):
        # Store values in the session
        self.session['username'] = 'jane'
        self.session['cart_items'] = [1, 2, 3]

        # Retrieve values from the session
        username = self.session.get('username')
        cart_items = self.session.get('cart_items', [])

        # Check if a key exists
        if 'username' in self.session:
            # User has a session
            pass

        # Delete values from the session
        del self.session['cart_items']

Outside of views, you can use get_request_session():

from plain.sessions import get_request_session

session = get_request_session(request)
session['key'] = 'value'

The session data is automatically saved when you set or delete values. Sessions are stored in the database using the Session model.

Settings

Setting Default Env var
SESSION_COOKIE_NAME "sessionid" -
SESSION_COOKIE_AGE 1209600 (2 weeks) -
SESSION_COOKIE_DOMAIN None -
SESSION_COOKIE_SECURE True -
SESSION_COOKIE_PATH "/" -
SESSION_COOKIE_HTTPONLY True -
SESSION_COOKIE_SAMESITE "Lax" -
SESSION_SAVE_EVERY_REQUEST False -
SESSION_EXPIRE_AT_BROWSER_CLOSE False -

See default_settings.py for more details.

Session expiration

Sessions expire SESSION_COOKIE_AGE seconds after they are last saved (not last accessed).

By default (SESSION_SAVE_EVERY_REQUEST = False), sessions are only saved when modified. For authenticated users, this means the expiration timer resets on login/logout but not when just browsing pages. Users will be logged out after SESSION_COOKIE_AGE even if actively using the site.

To extend sessions on every page access, set SESSION_SAVE_EVERY_REQUEST = True. This creates a sliding window where users stay logged in as long as they visit within SESSION_COOKIE_AGE, but increases database writes.

Session management

The SessionStore class provides additional methods for managing sessions.

Flushing sessions

To completely remove the current session data and regenerate the session key:

# In a view with SessionView
self.session.flush()

# Outside a view
from plain.sessions import get_request_session
session = get_request_session(request)
session.flush()

Cycling session keys

To create a new session key while retaining the current session data (useful for security purposes):

# In a view with SessionView
self.session.cycle_key()

# Outside a view
from plain.sessions import get_request_session
session = get_request_session(request)
session.cycle_key()

Checking if session is empty

# In a view with SessionView
if self.session.is_empty():
    # No session data exists
    pass

# Outside a view
from plain.sessions import get_request_session
session = get_request_session(request)
if session.is_empty():
    # No session data exists
    pass

Admin interface

You can view and manage sessions in the admin panel under the "Sessions" section. The admin interface allows you to:

  • Search sessions by session key
  • View session creation and expiration times
  • Delete expired or unwanted sessions

The SessionAdmin viewset provides the interface for managing sessions in the admin panel.

FAQs

How do I clear expired sessions?

You can use the built-in ClearExpired chore to delete expired sessions from the database:

plain chores run plain.sessions.chores.ClearExpired

You can schedule this chore to run periodically using plain.worker or your preferred task scheduler.

How do I access the underlying Session model instance?

You can access the database model instance through the model_instance property:

from plain.sessions import get_request_session

session = get_request_session(request)
session_instance = session.model_instance  # Returns the Session model or None

Why is my session not being saved?

Sessions are only saved when modified (when you set or delete a value). If you need the session to be saved on every request, set SESSION_SAVE_EVERY_REQUEST = True in your settings.

Installation

Install the plain.sessions package from PyPI:

uv add plain.sessions

Add plain.sessions to your INSTALLED_PACKAGES and include the SessionMiddleware in your middleware:

INSTALLED_PACKAGES = [
    # ...
    "plain.sessions",
]

MIDDLEWARE = [
    # ...
    "plain.sessions.middleware.SessionMiddleware",
    # ...
]

Run migrations to create the session table:

plain migrate plain.sessions