Regis' Blog

L'informatique, L'amour, Les vaches

Lost Django session keys?
October 05, 2014
|
Share this post
| |
Lost Django session keys?

If you use the sessions with Django as keys for your database (for example a basket), you are in front of a big problem each time your user wants to login and logout.

Indeed, Django change session key each time.

The problem

The problem is in fact simple, but I just lost half an hour to try to solve it. Imagine that you want a basket for an eCommerce website. There’s not so many solution to use the session key when your user is not authenticated!

class Order(models.Model):  
  # For non authenticated users 
  session = models.CharField(max_length=40) 

class OrderItem(models.Model):  
  order = models.ForeignKey(Order) 
  item = models.ForeignKey(Product) 
  # ...

However, each time the user login, he lost his order as well when he disconnect. We might want something else than using session keys.

Explanation

After a long search in my code, I try to find a solution on the Web (Stackoverflow is really a good friend) but as I didn’t found satisfactory solutions, I start to watch the Django source code.

The explanation is in the login and logout code. On each status change, Django changes the key for internal reasons, mostly with storing the database user ID.

With putting two print you may see:

def user_login(request):  
    if request.method == 'POST': 
        username = request.POST.get('username') 
        password = request.POST.get('password') 
        user = authenticate(username=username, password=password) 

        if user: 
            print request.session.session_key login(user, request) 
            print request.session.session_key 
    # ...

On my computer, it gave me : rucb8yjeyk19mtyj7af9dspth0z40s3e before login and 1fh96d0swdd2qhqxq7a22jrielbn8wi9 after.  Two different keys for the same user.

The solution

As you guess, you have to change the session key in all your tables (use a signal if there’s too many):

# Only for login but logout is the same 
old_key = request.session.session_key login(request, user)  
new_key = request.session.session_key Order.objects.filter(session=old_key).update(session=new_key)  

and everything goes fine, the user keeps his order (or anything else).

October 05, 2014
|
Share this post
| |