Sessions & Cookies

This post is part of my Django series. You can see an overview of the series along with instruction on how to get all the source code here.

This article assumes you are comfortable creating a Django project, can create apps and register them into the INSTALLED_APPS list of the settings file. If not please read my Django HelloWorld article.

This article assumes you have a project called DjangoSandBox in an application called sessionsandcookies.

Sessions

By default Django comes with the sessions middleware and applications installed:

#settings.py

# Application definition
INSTALLED_APPS = (
    'django.contrib.sessions',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
)

Note: If the settings were not present or you are starting a new project, ensure you have run migrate to create all the required schema and run all the required configuration scripts:

python manage.py migrate

Setting

Session data is stored as key value pairs within request.session which behaves as a dictionary. We set a value with [“key”] = value and get a value with get(“key”).

Session data is only valid for a certain amount of time. This is set to SESSION_COOKIE_AGE which defaults to two weeks.

We can use the get_expiry_date function to see the expiry date of the session data.

We can set the expiry with the set_expiry function which takes a time in seconds.

The following uses session data to set mark that a user has visited a page.

#views.py

from datetime import datetime

def sessions(request):
    context = {
        "has_visited": request.session.get("has_visited", False),
        "visited": request.session.get("visited", None),
        "expiry": request.session.get_expiry_date().strftime("%x %X")
    }

    if "has_visited" not in request.session:
        request.session['has_visited'] = str(True)
        request.session['visited'] = datetime.now().strftime("%x %X")
        request.session.set_expiry(10)  # Time in seconds. 0 expires when the browser is closed

    return render(request, 'sessionsandcookies/sessions.html', context)

A simple template to display the data we store and retrieve from the session data.

<!-- templates/sessionsandcookies/sessions.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sessions</title>
</head>
<body>
<h1>Sessions</h1>

{% if has_visited %}
    <span>Visited: {{ visited }}</span>
    <span>Expires: {{ expiry }}</span>
{% else %}
    First Page Land
{% endif %}

<span>
    <a href="{% url 'sessionsandcookies:sessions_clear' %}">Clear</a>
</span>
</body>
</html>

Hooking in our view function into the URL routing config:

# urls.py
url(r'^sessions/$', views.sessions, name="sessions"),

Note: don’t forget to hook our app into the project URL routing config.

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/sessions/

Clearing

We can use the clear function upon request.session to remove all session data. In this example we clear the session data and then redirect to the page in the previous example to prove we revert to the default value.

#view.py
def sessions_clear(request):
    if 'has_visited' in request.session:
        del request.session['has_visited']

    request.session.clear()

    return redirect(reverse("sessionsandcookies:sessions"))

Note: Above we call delete upon the session data element as well as clear; we can do both depending upon what we require.

Hooking in our view function into the URLrouting config.

#urls.py
url(r'^sessions/clear/$', views.sessions_clear, name="sessions_clear"),

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/sessions/clear/

Cookies

Not all browsers accept cookies so our first example is a way to test if the browser accepts cookies. We call set_test_cookie and then test_cookie_worked. The latter returns true if we can create cookies.

Testing

#views.py
def cookies_test(request):
    can_create_cookie = False
    request.session.set_test_cookie()

    if request.session.test_cookie_worked():
        request.session.delete_test_cookie()
        can_create_cookie = True

    return render(request, "sessionsandcookies/cookies_test.html", {"can_create_cookie": can_create_cookie})

A simple view which displays our result.

<!-- templates/sessionsandcookies/cookies_test.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Cookie</title>
</head>
<body>
<h1>Test Cookie</h1>

{% if can_create_cookie %}
    <span>Test cookie worked</span>
{% else %}
    <span>Test cookie did not work</span>
{% endif %}

<span>
    <a href="{% url 'sessionsandcookies:cookies' %}">Back</a>
</span>
</body>
</html>

Hooking in our function view into the URL routing config.

#urls.py
url(r'^cookies/test$', views.cookies_test, name="cookies_test"),

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/cookies/test

Setting

Setting cookie information is a little clunky in Django; we need to call set_cookie on the response object though we have to render our template to get hold of the response. We call render_to_response before calling set_cookies upon the returned response object.

#views.py
def cookies(request):
    hits = int(request.COOKIES.get('hits', '0'))
    first_hit = 'hits' not in request.COOKIES
    response = render_to_response('sessionsandcookies/cookies.html',
                                  {"first_hit": first_hit, "hits": hits}, RequestContext(request))

    response.set_cookie('hits', hits + 1, max_age=30)
    return response

A simple template view displays the number of hits which is passed into our template.

<!-- templates/sessionsandcookies/cookies.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cookies</title>
</head>
<body>

<h1>Cookies</h1>

<span>
{% if first_hit %}
    Your first hit!
{% else %}
    Hits: {{ hits }}
{% endif %}
</span>

</body>
</html>

Hooking in our view function into our URL routing config.

#urls.py
url(r'^cookies/$', views.cookies, name="cookies"),

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/cookies/

Expiring

We can expire our cookie by calling delete_cookie along with our cookie name.

#views.py
def cookies_expire(request):
    response =         render_to_response('sessionsandcookies/cookies_clear.html',
            {"first_hit": True, "hits": 0}, RequestContext(request))

    response.delete_cookie('hits')
    return response

A simple template which tells the user the cookies have been cleared along with a URL back to our page which shows the cookies data. We can then see the cookie hit count is reset to ‘first hit!’.

<! templates/sessionsandcookies/cookies_clear.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cookie Clear</title>
</head>
<body>
<h1>Cookie Clear</h1>

<span>The cookie was cleared</span>

<span>
    <a href="{% url 'sessionsandcookies:cookies' %}">Back</a>
</span>
</body>
</html>

Hooking in our view function into our URLrouting config.

#urls.py
url(r'^cookies/expire', views.cookies_expire, name="cookies_expire"),

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/cookies/expire/

References

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s