Skip to content

Django - Sessions

While cookies allow storing data on the client-side, sessions provide a mechanism to store user-specific data on the server-side. This is generally more secure for sensitive information, as the actual data doesn’t reside in the user’s browser.

How Sessions Work:

  1. When a user first visits a site using sessions, Django generates a unique, random session ID.
  2. Django sends this session ID back to the user’s browser, usually stored in a standard cookie.
  3. On subsequent requests from the same user, the browser sends the session ID cookie back to Django.
  4. Django uses this ID to look up the corresponding session data stored on the server (e.g., in the database, cache, or file system).
  5. The application can then read or write data associated with that specific user’s session.

This way, the only thing stored on the client is the session ID; the actual session data (like user ID, shopping cart contents, user preferences) remains on the server.

Django’s session framework is enabled by default in new projects created with django-admin startproject. It relies on specific middleware and an app being listed in your settings.py:

  1. Middleware: Ensure 'django.contrib.sessions.middleware.SessionMiddleware' is present in your MIDDLEWARE setting (usually placed after UpdateCacheMiddleware and before CommonMiddleware if using site-wide caching, otherwise its exact position is less critical but generally mid-list).
MIDDLEWARE = [
# ...
'django.contrib.sessions.middleware.SessionMiddleware',
# ...
]
  1. Installed App: Ensure 'django.contrib.sessions' is present in your INSTALLED_APPS setting.
INSTALLED_APPS = [
# ...
'django.contrib.sessions',
# ...
]
  1. Database Migrations: If you’re using the default database-backed sessions, you need to run migrations to create the necessary table (django_session).
python manage.py migrate

By default, Django stores session data in the database (django_session table). You can change this behavior using the SESSION_ENGINE setting in settings.py:

  • 'django.contrib.sessions.backends.db': Database (default). Reliable but can be slower under high load.
  • 'django.contrib.sessions.backends.cache': Uses your default cache backend. Faster but potentially volatile if the cache clears.
  • 'django.contrib.sessions.backends.cached_db': Writes to both database and cache (write-through cache). Reads from cache first, then database. Good balance.
  • 'django.contrib.sessions.backends.file': Stores sessions in files in a specified directory (SESSION_FILE_PATH).
  • 'django.contrib.sessions.backends.signed_cookies': Stores all session data directly in the client-side cookie, cryptographically signed. Avoids server-side storage needs but has cookie size limits and potential security implications if the signing key is compromised.

Example: Using cache-backed sessions

settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

When the session middleware is active, every HttpRequest object (the first argument to your view function, usually named request) will have a session attribute. This attribute behaves like a Python dictionary.

Let’s adapt the simple login example from the Cookies chapter to use sessions instead.

myapp/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .forms import LoginForm # Assuming a LoginForm exists
def login_session_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
# Store username in the session
request.session['username'] = username
request.session['login_time'] = str(datetime.datetime.now()) # Store login time
# Set session expiry (e.g., 30 minutes of inactivity)
request.session.set_expiry(1800)
return redirect('session_status') # Redirect to a status page
else:
return render(request, 'login.html', {'form': form})
else:
form = LoginForm()
return render(request, 'login.html', {'form': form})
def session_status_view(request):
# Use .get() for safe access to session data
username = request.session.get('username')
if username:
# User is logged in via session
login_time = request.session.get('login_time', 'N/A')
expiry_age = request.session.get_expiry_age()
return render(request, 'loggedin.html', {
'username': username,
'login_time': login_time,
'expiry_seconds': expiry_age
})
else:
# No active session or username not set
return redirect('login_session') # Redirect back to login
def logout_session_view(request):
# Clear the session data entirely
request.session.flush()
return render(request, 'logout_message.html')
# Add URL patterns in myapp/urls.py for:
# path('login/', views.login_session_view, name='login_session')
# path('status/', views.session_status_view, name='session_status')
# path('logout/', views.logout_session_view, name='logout_session')

Key Session Operations:

  • Storing data: request.session['my_key'] = 'my_value'
  • Retrieving data: value = request.session.get('my_key', 'default_if_not_found') (using .get() is safer than request.session['my_key'])
  • Deleting data: del request.session['my_key'] (raises KeyError if key doesn’t exist)
  • Checking existence: 'my_key' in request.session
  • Clearing all session data: request.session.flush() (effectively logs the user out)
  • Setting expiry: request.session.set_expiry(value) where value can be seconds (integer), a datetime object, or 0 (expire on browser close), or None (use global setting).
  • Getting expiry info: request.session.get_expiry_age() (seconds left), request.session.get_expiry_date() (datetime object).
  • Checking browser-close expiry: request.session.get_expire_at_browser_close() (returns True or False).

You can control global session behavior via settings in settings.py:

  • SESSION_COOKIE_AGE: Default age of session cookies, in seconds (e.g., 1209600 for 2 weeks).
  • SESSION_COOKIE_HTTPONLY: Set to True (default) to prevent client-side JavaScript access to the session cookie.
  • SESSION_COOKIE_SECURE: Set to True if your site only uses HTTPS.
  • SESSION_COOKIE_SAMESITE: Controls cross-site cookie behavior (‘Lax’ is default, ‘Strict’ or ‘None’ are options).
  • SESSION_EXPIRE_AT_BROWSER_CLOSE: Set to True if you want sessions to expire when the browser closes (overrides SESSION_COOKIE_AGE).
  • SESSION_SAVE_EVERY_REQUEST: If True, the session is saved on every single request, even if unmodified. Default is False (saves only when session data changes), which is more efficient.

Sessions are fundamental for building stateful web applications in Django, especially for handling user authentication and personalized experiences.

Further Reading: