How to set and get cookies in Django?

183.7k views Asked by At

I have a web site which shows different content based on a location the visitor chooses. e.g: User enters in 55812 as the zip. I know what city and area lat/long. that is and give them their content pertinent to that area. My question is how can I store this in a cookie so that when they return they are not required to always enter their zip code?

I see it as follows:

  1. Set persistent cookie based on their area.
  2. When they return read cookie, grab zipcode.
  3. Return content based on the zip code in their cookie.

I can't seem to find any solid information on setting a cookie. Any help is greatly appreciated.

6

There are 6 answers

7
jujule On BEST ANSWER

UPDATE : check Peter's answer below for a builtin solution :

This is a helper to set a persistent cookie:

import datetime

def set_cookie(response, key, value, days_expire=7):
    if days_expire is None:
        max_age = 365 * 24 * 60 * 60  # one year
    else:
        max_age = days_expire * 24 * 60 * 60
    expires = datetime.datetime.strftime(
        datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age),
        "%a, %d-%b-%Y %H:%M:%S GMT",
    )
    response.set_cookie(
        key,
        value,
        max_age=max_age,
        expires=expires,
        domain=settings.SESSION_COOKIE_DOMAIN,
        secure=settings.SESSION_COOKIE_SECURE or None,
    )

Use the following code before sending a response.

def view(request):
    response = HttpResponse("hello")
    set_cookie(response, 'name', 'jujule')
    return response

UPDATE : check Peter's answer below for a builtin solution :

2
Ben Regenspan On

You could manually set the cookie, but depending on your use case (and if you might want to add more types of persistent/session data in future) it might make more sense to use Django's sessions feature. This will let you get and set variables tied internally to the user's session cookie. Cool thing about this is that if you want to store a lot of data tied to a user's session, storing it all in cookies will add a lot of weight to HTTP requests and responses. With sessions the session cookie is all that is sent back and forth (though there is the overhead on Django's end of storing the session data to keep in mind).

5
Peter On

Using Django's session framework should cover most scenarios, but Django also now provide direct cookie manipulation methods on the request and response objects (so you don't need a helper function).

Setting a cookie:

def view(request):
  response = HttpResponse('blah')
  response.set_cookie('cookie_name', 'cookie_value')

Retrieving a cookie:

def view(request):
  value = request.COOKIES.get('cookie_name')
  if value is None:
    # Cookie is not set

  # OR

  try:
    value = request.COOKIES['cookie_name']
  except KeyError:
    # Cookie is not set
0
Super Kai - Kazuya Ito On

You can set cookies in these ways as shown below. *You must return the object otherwise cookies are not set to a browser different from Django sessions which can set the session id cookies to a browser without returning the object and you can see my question and my answer which explain why to use response.set_cookie() rather than response.cookies[] to set cookies and I asked the question about how to set a dictionary or list to a cookie and get it properly and you can see my answer explaining how to delete cookies.

render() and set_cookie():

from django.shortcuts import render

def my_view(request):
    response = render(request, 'index.html', {})
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object

render_to_string(), HttpResponse() and set_cookie():

from django.template.loader import render_to_string
from django.http import HttpResponse

def my_view(request):
    rts = render_to_string('index.html', {})
    response = HttpResponse(rts)
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object

HttpResponse() and set_cookie():

from django.http import HttpResponse

def my_view(request):
    response = HttpResponse('View')
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object

redirect() and set_cookie():

from django.shortcuts import redirect

def my_view(request):
    response = redirect('https://example.com/')
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object

HttpResponseRedirect() and set_cookie():

from django.http import HttpResponseRedirect

def my_view(request):
    response = HttpResponseRedirect('https://example.com/')
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object

And, you can get the cookies with request.COOKIES['key'] and request.COOKIES.get('key') as shown below. *request.COOKIES.get() returns None by default if the key doesn't exist and you can change None to other value like Doesn't exist by setting it to the 2nd argument as shown below:

from django.shortcuts import render

def my_view(request):
    print(request.COOKIES['name']) # John
    print(request.COOKIES.get('age')) # 27
    print(request.COOKIES.get('gender')) # None
    print(request.COOKIES.get('gender', "Doesn't exist")) # Doesn't exist
    return render(request, 'index.html', {})

And, you can get cookies with request.COOKIES.key in Django Templates as shown below:

# "templates/index.html"

{{ request.COOKIES.name }} {# John #}
{{ request.COOKIES.age }} {# 27 #}

And, you can delete the cookies with response.delete_cookie() as shown below. *You must return the object otherwise cookies are not deleted from a browser:

from django.shortcuts import render

def my_view(request):
    response = render(request, 'index.html', {})
    response.delete_cookie('name')
    response.delete_cookie('age')
    return response # Must return the object
0
Chris Conlan On

Anyone interested in doing this should read the documentation of the Django Sessions framework. It stores a session ID in the user's cookies, but maps all the cookies-like data to your database. This is an improvement on the typical cookies-based workflow for HTTP requests.

Here is an example with a Django view ...

def homepage(request):

    request.session.setdefault('how_many_visits', 0)
    request.session['how_many_visits'] += 1

    print(request.session['how_many_visits'])

    return render(request, 'home.html', {})

If you keep visiting the page over and over, you'll see the value start incrementing up from 1 until you clear your cookies, visit on a new browser, go incognito, or do anything else that sidesteps Django's Session ID cookie.

0
abdullahselek On

In addition to jujule's answer below you can find a solution that shows how to set a cookie to Class Based Views responses. You can apply this solution to your view classes that extends from TemplateView, ListView or View.

Below a modified version of jujule's persistent cookie setter method:

import datetime

from django.http import HttpResponse


def set_cookie(
    response: HttpResponse,
    key: str,
    value: str,
    cookie_host: str,
    days_expire: int = 365,
):
    max_age = days_expire * 24 * 60 * 60
    expires = datetime.datetime.strftime(
        datetime.datetime.utcnow() + datetime.timedelta(days=days_expire), "%a, %d-%b-%Y %H:%M:%S GMT",
    )
    domain = cookie_host.split(":")[0]
    response.set_cookie(
        key,
        value,
        max_age=max_age,
        expires=expires,
        domain=domain,
        secure=False,
    )

And sample class based view example that adds a cookie using persistent cookie setter

class BaseView(TemplateView):
    template_name = "YOUR_TEMPLATE_FILE_PATH"

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        set_cookie(
            response=response,
            key="COOKIE_KEY",
            value="COOKIE_VALUE",  
            cookie_host=request.get_host(),
            days_expire=7,
        )
        return response