Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow setting HttpResponse cookie expiry times with datetime objects.

Patch from SmileyChris. Fixed #7770.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13809 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 2d4da641a6ee6c96f38336d8dc6786c07e7b3a1f 1 parent 7c07544
Malcolm Tredinnick malcolmt authored
28 django/http/__init__.py
View
@@ -1,5 +1,7 @@
+import datetime
import os
import re
+import time
from Cookie import BaseCookie, SimpleCookie, CookieError
from pprint import pformat
from urllib import urlencode
@@ -12,6 +14,7 @@
from django.utils.datastructures import MultiValueDict, ImmutableList
from django.utils.encoding import smart_str, iri_to_uri, force_unicode
+from django.utils.http import cookie_date
from django.http.multipartparser import MultiPartParser
from django.conf import settings
from django.core.files import uploadhandler
@@ -373,11 +376,32 @@ def get(self, header, alternate):
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False):
+ """
+ Sets a cookie.
+
+ ``expires`` can be a string in the correct format or a
+ ``datetime.datetime`` object in UTC. If ``expires`` is a datetime
+ object then ``max_age`` will be calculated.
+ """
self.cookies[key] = value
+ if expires is not None:
+ if isinstance(expires, datetime.datetime):
+ delta = expires - expires.utcnow()
+ # Add one second so the date matches exactly (a fraction of
+ # time gets lost between converting to a timedelta and
+ # then the date string).
+ delta = delta + datetime.timedelta(seconds=1)
+ # Just set max_age - the max_age logic will set expires.
+ expires = None
+ max_age = max(0, delta.days * 86400 + delta.seconds)
+ else:
+ self.cookies[key]['expires'] = expires
if max_age is not None:
self.cookies[key]['max-age'] = max_age
- if expires is not None:
- self.cookies[key]['expires'] = expires
+ # IE requires expires, so set it if hasn't been already.
+ if not expires:
+ self.cookies[key]['expires'] = cookie_date(time.time() +
+ max_age)
if path is not None:
self.cookies[key]['path'] = path
if domain is not None:
7 docs/ref/request-response.txt
View
@@ -529,8 +529,11 @@ Methods
* ``max_age`` should be a number of seconds, or ``None`` (default) if
the cookie should last only as long as the client's browser session.
- * ``expires`` should be a string in the format
- ``"Wdy, DD-Mon-YY HH:MM:SS GMT"``.
+ If ``expires`` is not specified, it will be calculated.
+ * ``expires`` should either be a string in the format
+ ``"Wdy, DD-Mon-YY HH:MM:SS GMT"`` or a ``datetime.datetime`` object
+ in UTC. If ``expires`` is a ``datetime`` object, the ``max_age``
+ will be calculated.
* Use ``domain`` if you want to set a cross-domain cookie. For example,
``domain=".lawrence.com"`` will set a cookie that is readable by
the domains www.lawrence.com, blogs.lawrence.com and
25 tests/regressiontests/requests/tests.py
View
@@ -1,5 +1,5 @@
"""
->>> from django.http import HttpRequest
+>>> from django.http import HttpRequest, HttpResponse
>>> print repr(HttpRequest())
<HttpRequest
GET:{},
@@ -44,4 +44,27 @@
>>> request.path = ''
>>> print request.build_absolute_uri(location="/path/with:colons")
http://www.example.com/path/with:colons
+
+
+# Test cookie datetime expiration logic
+>>> from datetime import datetime, timedelta
+>>> delta = timedelta(seconds=10)
+>>> response = HttpResponse()
+>>> response.set_cookie('datetime', expires=datetime.utcnow()+delta)
+>>> datetime_cookie = response.cookies['datetime']
+>>> datetime_cookie['max-age']
+10
+>>> response.set_cookie('datetime', expires=datetime(2028, 1, 1, 4, 5, 6))
+>>> response.cookies['datetime']['expires']
+'Sat, 01-Jan-2028 04:05:06 GMT'
+
+# Test automatically setting cookie expires if only max_age is provided
+>>> response.set_cookie('max_age', max_age=10)
+>>> max_age_cookie = response.cookies['max_age']
+>>> max_age_cookie['max-age']
+10
+>>> from django.utils.http import cookie_date
+>>> import time
+>>> max_age_cookie['expires'] == cookie_date(time.time()+10)
+True
"""
Please sign in to comment.
Something went wrong with that request. Please try again.