28

I want to set a cookie inside a view and then have that view render a template. As I understand it, this is the way to set a cookie:

def index(request):
    response = HttpResponse('blah')
    response.set_cookie('id', 1)
    return response

However, I want to set a cookie and then render a template, something like this:

def index(request, template):
    response_obj = HttpResponse('blah')
    response_obj.set_cookie('id', 1)
    return render_to_response(template, response_obj)   # <= Doesn't work

The template will contain links that when clicked will execute other views that check for the cookie I'm setting. What's the correct way to do what I showed in the second example above? I understand that I could create a string that contains all the HTML for my template and pass that string as the argument to HttpResponse but that seems really ugly. Isn't there a better way to do this? Thanks.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Jim
  • 13,430
  • 26
  • 104
  • 155

6 Answers6

40

This is how to do it:

from django.shortcuts import render

def home(request, template):
    response = render(request, template)  # django.http.HttpResponse
    response.set_cookie(key='id', value=1)
    return response
micrypt
  • 431
  • 4
  • 10
Jim
  • 13,430
  • 26
  • 104
  • 155
  • 4
    You first instantiate a HttpResponse but do nothing with it. `render` returns a response, which you assign into the same variable on which you then set the cookie and which you finally return. Your answer would be equivalent with the line `response = HttpResponse()` removed. – Santtu Pajukanta Jul 18 '14 at 18:50
  • 7
    I may have misunderstood something, but wasn't the question "how to set a cookie *before* rendering the template"? – vmonteco Jun 22 '16 at 01:57
  • @vmonteco that's how the question may have been phrased, but I can't think of any use cases where it makes a difference whether the cookie is set before or after the rendering. As long as it goes out with the response, all the downstream logic would be blind to the ordering. – Dr Phil Aug 05 '22 at 00:31
  • @DrPhil A wild guess about the usecase would be to render a cookie value in the template for whatever reason. I'm unsure about the safety concerns or about the good practices though. But the behavior would be different. – vmonteco Sep 06 '22 at 03:58
6

If you just need the cookie value to be set when rendering your template, you could try something like this :

def view(request, template):
    # Manually set the value you'll use for rendering
    # (request.COOKIES is just a dictionnary)
    request.COOKIES['key'] = 'val'
    # Render the template with the manually set value
    response = render(request, template)
    # Actually set the cookie.
    response.set_cookie('key', 'val')

    return response
vmonteco
  • 14,136
  • 15
  • 55
  • 86
5

The accepted answer sets the cookie before the template is rendered. This works.

response = HttpResponse()
response.set_cookie("cookie_name", "cookie_value")
response.write(template.render(context))
James Doe 33
  • 59
  • 1
  • 1
0
                response = render(request, 'admin-dashboard.html',{"email":email})
                #create cookies
                expiry_time = 60 * 60 #in seconds
                response.set_cookie("email_cookie",email,expiry_time);
                response.set_cookie("classname","The easylearn academy",expiry_time);
0

You can set cookies and render a template 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 answer explaining how to set and get cookies in Django.

render() and set_cookie():

from django.shortcuts import render

def my_view(request, template):
    response = render(request, template)
    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, template):
    rts = render_to_string(template)
    response = HttpResponse(rts)
    response.set_cookie('name', 'John')
    response.cookies['age'] = 27
    return response # Must return the object set
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
-1
def index(request, template):
    response = HttpResponse('blah')
    response.set_cookie('id', 1)
    id = request.COOKIES.get('id')
    return render_to_response(template,{'cookie_id':id})
Manjunath
  • 150
  • 1
  • 6
  • Then in your template you can show the links based on whether your cookie is set or not. Ex: {% if cookie_id %} #links to be displayed {%endif%} – Manjunath Jun 12 '13 at 04:34
  • Thank you for responding. However, this doesn't look right. Your code is looking for a cookie called 'id' in the request. However, the cookie isn't being set until after that request was received so it's not going to be there. – Jim Jun 12 '13 at 04:41
  • I guess one simple way to do it would be just to run some JavaScript on the client side when the template is rendered that creates the cookie. But I'm still curious as to whether what I'm asking about above can be done server-side. – Jim Jun 12 '13 at 05:05
  • I'm not getting an error but the code you showed doesn't work, I think for the reason I described. – Jim Jun 12 '13 at 05:23
  • try this id = request.COOKIES.get('id',None) – Manjunath Jun 12 '13 at 05:26