title: Most optimized way to delete all sessions for a specific user in Django?
body: <p>I'm running Django 1.3, using Sessions Middleware and Auth Middleware:</p>
  
  <pre><code># settings.py
  
  SESSION_ENGINE = django.contrib.sessions.backends.db   # Persist sessions to DB
  SESSION_COOKIE_AGE = 1209600                           # Cookies last 2 weeks
  </code></pre>
  
  <p>Each time a user logs in from a different location (different computer/browser), a new <code>Session()</code> is created and saved with a unique <code>session_id</code>. This can result in multiple database entries for the same user. Their login persists on that node until the cookie is deleted or session expires.</p>
  
  <p>When a user changes their password, I want to delete all unexpired sessions for that user from the DB. That way after a password change, they're forced to re-login. This is for security purposes, such as if your computer got stolen, or you accidentally left yourself logged-in on a public terminal.</p>
  
  <p><strong>I want to know the best way to optimize this.</strong> Here's how I've done it:</p>
  
  <pre><code># sessions_helpers.py
  
  from django.contrib.sessions.models import Session
  import datetime
  
  def all_unexpired_sessions_for_user(user):
      user_sessions = []
      all_sessions  = Session.objects.filter(expire_date__gte=datetime.datetime.now())
      for session in all_sessions:
          session_data = session.get_decoded()
          if user.pk == session_data.get('_auth_user_id'):
              user_sessions.append(session)
      return user_sessions
  
  def delete_all_unexpired_sessions_for_user(user, session_to_omit=None):
      for session in all_unexpired_sessions_for_user(user):
          if session is not session_to_omit:
              session.delete()
  </code></pre>
  
  <p>A very simplified view:</p>
  
  <pre><code># views.py
  
  from django.http import HttpResponse
  from django.shortcuts import render_to_response
  from myapp.forms import ChangePasswordForm
  from sessions_helpers import delete_all_unexpired_sessions_for_user
  
  @never_cache
  @login_required
  def change_password(request):
      user = request.user
  
      if request.method == 'POST':
          form = ChangePasswordForm(data=request)
  
          if form.is_valid():
              user.set_password(form.get('password'))
              user.save()
              request.session.cycle_key()         # Flushes and replaces old key. Prevents replay attacks.
              delete_all_unexpired_sessions_for_user(user=user, session_to_omit=request.session)
              return HttpResponse('Success!')
  
      else:
          form = ChangePasswordForm()
  
      return render_to_response('change_password.html', {'form':form}, context_instance=RequestContext(request))
  </code></pre>
  
  <p>As you can see in <code>sessions_helpers.py</code>, I have to pull every unexpired session out of the DB, <code>Session.objects.filter(expire_date__gte=datetime.datetime.now())</code>, decode all of them, and then check to see if it matches a user or not. This will be extremely costly to the database if there are, say, 100,000+ sessions stored in there.</p>
  
  <p>Is there a more-database-friendly way to do this? Is there a Sessions/Auth Middleware setting that'll let you store the username as a column in the Sessions table so I can run SQL against that, or will I have to modify Sessions to do that? Out-of-the-box it only has <code>session_key</code>, <code>session_data</code>, and <code>expire_date</code> columns.</p>
  
  <p>Thanks for any insight or help you can offer. :)</p>