Working with Sessions/Cookies in Django

Django provides a session framework that lets you store and retrieve data on a per-site-visitor basis. Django abstracts the process of sending and receiving cookies, by placing a session ID cookie on the client side, and storing all the related data on the server side. So the data itself is not stored client side. This is nice from a security perspective.

Also since the Django sessions framework is cookie-based, session IDs are not put in the URLs (as is often the case with PHP). According to the Django documentation this was an intentional design decision, which means that URLs remain clean and the site is less vulnerable to session ID theft via the “Referer” header.

Setting up Sessions

To enable the session functionality, you’ll need to make sure that the MIDDLEWARE_CLASSES in settings.py has ‘django.contrib.sessions.middleware.SessionMiddleware’ activated.

There are different ways in which you can configure the session engine which controls how it stores sessions, i.e. in a database or in a cache. The simplest way is to use the default option and store the data in a model/database (i.e. django.contrib.sessions.models.Session), is by adding ‘django.contrib.sessions’ to your INSTALLED_APPS.

You will have to run python manage.py syncdb to create the session database table.

Testing Cookies

To test out whether cookies work on your client, you can use some convenience methods provided by Django’s request object (set_test_cookie(), test_cookie_worked(), delete_test_cookie() ). In one view you will need to set a cookie and in another view you’ll need to test it. The reason you need to set the cookie in one view and test it in another is that you need to wait to see if the client has actually accepted the cookie.

In views.py, set the test cookie in the index view, and test the cookie in your about view.

def index(request):

        ...

        request.session.set_test_cookie()

        ...


def about(request):

        ...

        if request.session.test_cookie_worked():
                print "The test cookie worked!!!"
                request.session.delete_test_cookie()

        ...

Visit the index page, and then visit the about page. Examine the output in the console, hopefully, you’ll see that “The test cookie worked!!!” has been printed out to the console.

Add and Using Cookies

Everyone loves knowing how many times they have visited a site. Hmmm, maybe not, but let’s add that functionality now using cookies as an example.

To do this you’ll need two cookies. One to track the number of times, and one to keep track of when the user last visited the site, so that you can increment the visit count only once per day.

In views.py, add and update the code in the index view function:

def index(request):

        ....
        ....

        visits = int( request.COOKIES.get('visits', '0') )

        response =  HttpResponse(template.render(context))

        if request.COOKIES.has_key('last_visit' ):
                last_visit = request.COOKIES['last_visit']
                # the cookie is a string - convert back to a datetime type
                last_visit_time = datetime.strptime(last_visit[:-7], "%Y-%m-%d %H:%M:%S")
                curr_time = datetime.now()
                if (curr_time-last_visit_time).days > 0:
                        # if at least one day has gone by then inc the visit count.
                        response.set_cookie('visits', visits + 1 )
                        response.set_cookie('last_visit', datetime.now())
        else:
                response.set_cookie('last_visit', datetime.now())

        return response

To report the number of times that the page has been viewed, update the about view function, as follows:

def about(request):
        context = RequestContext(request)

        ...

        if request.COOKIES.has_key( 'visits' ):
                v = request.COOKIES[ 'visits' ]
        else:
                v = 0

        return render_to_response('rango/about.html', {'visits': v}, context)

Now in the rango/about.html template add in a new paragraph that informs the users how many times they have visited the site.

Browser-length sessions vs. persistent sessions

Note that you can control whether the session framework uses browser-length sessions vs. persistent sessions with the SESSION_EXPIRE_AT_BROWSER_CLOSE setting. By default, SESSION_EXPIRE_AT_BROWSER_CLOSE is set to False, which means session cookies will be stored in users’ browsers for as long as SESSION_COOKIE_AGE. This is useful if you don’t want people to have to log in each time they open the web browser. However, Django will use browser-length cookies if SESSION_EXPIRE_AT_BROWSER_CLOSE is set to True. These cookies will expire as soon as the user closes their browser.