19

I hit a problem when get session_key from request.session.

I am using Django1.8 and Python2.7.10 to set up a RESTful service.

Here is snippet of my login view:

user = authenticate(username=userName, password=passWord)
if user is not None:
    # the password verified for the user
    if user.is_active:
        # app_logger.debug("User is valid, active and authenticated")
        if hasattr(user, 'parent') :
            login(request, user)
            request.session['ut'] = 4 
            # user type 1 means admin, 2 for teacher, 3 for student, 4 for parents
            request.session['uid'] = user.id
            description = request.POST.get('description','')

            request.session['realname'] = user.parent.realname
            request.session['pid'] = user.parent.id
            devicemanage.update_user_device(devicetoken, user.id, ostype, description) 
            children = parentmanage.get_children_info(user.parent.id)
            session_id = request.session.session_key
            user.parent.login_status = True
            user.parent.save()
            return JsonResponse({'retcode': 0,'notify_setting':{'receive_notify':user.parent.receive_notify,'notify_with_sound':user.parent.notify_with_sound,'notify_sound':user.parent.notify_sound,'notify_shake':user.parent.notify_shake},'pid':user.parent.id,'children':children,'name':user.parent.realname,'sessionid':session_id,'avatar':user.parent.avatar,'coins':user.parent.coins})

Now when this function is called, I see sometimes session_id is None within the response.

So, after debugging (I set breakpoint at the return JsonResponse(...) line), I see that when I hit the breakpoint the request.session._session_key is None, but request.session.session_key is u'j4lhxe8lvk7j4v5cmkfzytyn5235chf1' and session_id is also None.

Does anyone know how can this happen? Why isn't the value of session_key set when assigning it to session_id before returning the response?

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
Wesley
  • 1,857
  • 2
  • 16
  • 30
  • 3
    If `request.session.session_key` is None, that means the session object is brand-new and hasn't been saved to the db yet. Calling `request.session.save()` should populate that attribute. – John Gordon Aug 27 '16 at 15:36

2 Answers2

34

According to John's suggestion.

I fixed the problem by this snippet:

if not request.session.session_key:
    request.session.save()
session_id = request.session.session_key
Wesley
  • 1,857
  • 2
  • 16
  • 30
11

As per documentation:

SessionStore.create() is designed to create a new session (i.e. one not loaded from the session store and with session_key=None). save() is designed to save an existing session (i.e. one loaded from the session store). Calling save() on a new session may also work but has a small chance of generating a session_key that collides with an existing one. create() calls save() and loops until an unused session_key is generated.

Means it is safer to use create() instead of save(). So you can try like this:

if not request.session.session_key:
    request.session.create()
session_id = request.session.session_key
ruddra
  • 50,746
  • 7
  • 78
  • 101
  • 2
    The docs are wrong here, if you look at the code (at least for the db backend) when the session is new, calling save calls create, so theres no chance of colliding ids. So its better to directly call save and avoid the "if" part – ladorm Oct 23 '19 at 23:57