Ticket #2548: session_middleware.14.diff

File session_middleware.14.diff, 10.0 KB (added by SmileyChris, 8 years ago)

Patch supporting both custom idle-time expiration and fixed date expiration.

  • AUTHORS

     
    260260    tstromberg@google.com
    261261    Makoto Tsuyuki <mtsuyuki@gmail.com>
    262262    tt@gurgle.no
    263     Amit Upadhyay
     263    Amit Upadhyay <http://www.amitu.com/blog/>
    264264    Geert Vanderkelen
    265265    viestards.lists@gmail.com
    266266    Vlado <vlado@labath.org>
  • django/contrib/sessions/middleware.py

     
    5151    def delete_test_cookie(self):
    5252        del self[TEST_COOKIE_NAME]
    5353
     54    def get_max_age(self):
     55        expiry = self.get('_session_expiry')
     56        if not expiry:   # Checks both None and 0 cases
     57            return settings.SESSION_COOKIE_AGE
     58        if not isinstance(expiry, datetime.datetime):
     59            return expiry
     60        delta = expiry - datetime.datetime.now()
     61        return delta.days * 86400 + delta.seconds
     62
     63    def get_expiry_date(self):
     64        expiry = self.get('_session_expiry', settings.SESSION_COOKIE_AGE)
     65        if isinstance(expiry, datetime.datetime):
     66            return expiry
     67        return datetime.datetime.now() + datetime.timedelta(seconds=expiry)
     68
     69    def set_expiry(self, value):
     70        """
     71        Sets a custom expiration for the session. ``value`` can be an integer, a
     72        Python ``datetime`` or ``timedelta`` object or ``None``.
     73
     74        If ``value`` is an integer, the session will expire after that many
     75        seconds of inactivity. If set to ``0`` then the session will expire on
     76        browser close.
     77
     78        If ``value`` is a ``datetime`` or ``timedelta`` object, the session
     79        will expire at that specific future time.
     80
     81        If ``value`` is ``None``, the session uses the global session expiry
     82        policy.
     83        """
     84        if value is None:
     85            # Remove any custom expiration for this session.
     86            try:
     87                del self['_session_expiry']
     88            except KeyError:
     89                pass
     90            return
     91        if isinstance(value, datetime.timedelta):
     92            value = datetime.datetime.now() + value
     93        self['_session_expiry'] = value
     94
     95    def get_expire_at_browser_close(self):
     96        if self.get('_session_expiry') is None:
     97            return settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
     98        return self.get('_session_expiry') == 0
     99
    54100    def _get_session(self):
    55101        # Lazily loads session from storage.
    56102        self.accessed = True
     
    95141                    obj = Session.objects.get_new_session_object()
    96142                    session_key = obj.session_key
    97143
    98                 if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
    99                     max_age = None
    100                     expires = None
    101                 else:
    102                     max_age = settings.SESSION_COOKIE_AGE
    103                     rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE)
     144                if request.session.get_expire_at_browser_close():
     145                    max_age = None 
     146                    expires = None 
     147                else: 
     148                    max_age = request.session.get_max_age()
     149                    rfcdate = formatdate(time.time() + max_age)
    104150                    # Fixed length date must have '-' separation in the format
    105151                    # DD-MMM-YYYY for compliance with Netscape cookie standard
    106152                    expires = (rfcdate[:7] + "-" + rfcdate[8:11]
    107153                               + "-" + rfcdate[12:26] + "GMT")
    108                 new_session = Session.objects.save(session_key, request.session._session,
    109                     datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
     154                Session.objects.save(session_key, request.session._session,
     155                                     request.session.get_expiry_date())
    110156                response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
    111                     max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
     157                    max_age=max_age, expires=expires,
     158                    domain=settings.SESSION_COOKIE_DOMAIN,
    112159                    secure=settings.SESSION_COOKIE_SECURE or None)
    113160        return response
  • django/contrib/sessions/tests.py

     
    2626
    2727>>> s.pop('some key', 'does not exist')
    2828'does not exist'
     29
     30#########################
     31# Custom session expiry #
     32#########################
     33
     34>>> from django.conf import settings
     35>>> from datetime import datetime, timedelta
     36
     37>>> td9 = timedelta(seconds=9)
     38>>> td10 = timedelta(seconds=10)
     39>>> td11 = timedelta(seconds=11)
     40
     41# A normal session has a max age equal to settings
     42>>> s.get_max_age() == settings.SESSION_COOKIE_AGE
     43True
     44
     45# So does a custom session with an idle expiration time of 0 (but it'll expire
     46# at browser close)
     47>>> s.set_expiry(0)
     48>>> s.get_max_age() == settings.SESSION_COOKIE_AGE
     49True
     50
     51# Custom session idle expiration time
     52>>> s.set_expiry(10)
     53>>> s.get_expiry_date() == datetime.now() + td10
     54True
     55>>> s.get_max_age()
     5610
     57
     58# Custom session fixed expiry date (timedelta)
     59>>> s.set_expiry(td10)
     60>>> s.get_expiry_date() == datetime.now() + td10
     61True
     62>>> s.get_max_age()
     6310
     64
     65# Custom session fixed expiry date (fixed datetime)
     66>>> s.set_expiry(datetime.now() + td10)
     67>>> s.get_expiry_date() == datetime.now() + td10
     68True
     69>>> s.get_max_age()
     7010
     71
     72# Set back to default session age
     73>>> s.set_expiry(None)
     74>>> s.get_max_age() == settings.SESSION_COOKIE_AGE
     75True
     76
     77# Allow to set back to default session age even if no alternate has been set
     78>>> s.set_expiry(None)
     79
     80
     81# We're changing the setting then reverting back to the original setting at the
     82# end of these tests.
     83>>> original_expire_at_browser_close = settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
     84>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False
     85
     86# Custom session age
     87>>> s.set_expiry(10)
     88>>> s.get_expire_at_browser_close()
     89False
     90
     91# Custom expire-at-browser-close
     92>>> s.set_expiry(0)
     93>>> s.get_expire_at_browser_close()
     94True
     95
     96# Default session age
     97>>> s.set_expiry(None)
     98>>> s.get_expire_at_browser_close()
     99False
     100
     101>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = True
     102
     103# Custom session age
     104>>> s.set_expiry(10)
     105>>> s.get_expire_at_browser_close()
     106False
     107
     108# Custom expire-at-browser-close
     109>>> s.set_expiry(0)
     110>>> s.get_expire_at_browser_close()
     111True
     112
     113# Default session age
     114>>> s.set_expiry(None)
     115>>> s.get_expire_at_browser_close()
     116True
     117
     118>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = original_expire_at_browser_close
    29119"""
    30120
    31121from django.contrib.sessions.middleware import SessionWrapper
  • docs/sessions.txt

     
    3939It implements the following standard dictionary methods:
    4040
    4141    * ``__getitem__(key)``
     42
    4243      Example: ``fav_color = request.session['fav_color']``
    4344
    4445    * ``__setitem__(key, value)``
     46
    4547      Example: ``request.session['fav_color'] = 'blue'``
    4648
    4749    * ``__delitem__(key)``
     50
    4851      Example: ``del request.session['fav_color']``. This raises ``KeyError``
    4952      if the given ``key`` isn't already in the session.
    5053
    5154    * ``__contains__(key)``
     55
    5256      Example: ``'fav_color' in request.session``
    5357
    5458    * ``get(key, default=None)``
     59
    5560      Example: ``fav_color = request.session.get('fav_color', 'red')``
    5661
    5762    * ``keys()``
    5863
    5964    * ``items()``
    6065
    61 It also has these three methods:
     66It also has these methods:
    6267
    6368    * ``set_test_cookie()``
     69
    6470      Sets a test cookie to determine whether the user's browser supports
    6571      cookies. Due to the way cookies work, you won't be able to test this
    6672      until the user's next page request. See "Setting test cookies" below for
    6773      more information.
    6874
    6975    * ``test_cookie_worked()``
     76
    7077      Returns either ``True`` or ``False``, depending on whether the user's
    7178      browser accepted the test cookie. Due to the way cookies work, you'll
    7279      have to call ``set_test_cookie()`` on a previous, separate page request.
    7380      See "Setting test cookies" below for more information.
    7481
    7582    * ``delete_test_cookie()``
     83
    7684      Deletes the test cookie. Use this to clean up after yourself.
    7785
     86    * ``set_expiry(value)``
     87
     88      Sets a custom expiration for the session.
     89
     90      If ``value`` is an integer, the session will expire after that many
     91      seconds of inactivity. If set to ``0`` then the session will expire when
     92      the user's browser is closed.
     93
     94      If ``value`` is a ``datetime`` or ``timedelta`` object, the session will
     95      expire at that specific time.
     96
     97      If ``value`` is ``None``, the session reverts to using the global session
     98      expiry policy.
     99
     100    * ``get_max_age()``
     101
     102      Returns the number of seconds until this session expires. For sessions
     103      with no custom expiration (or those set to expire at browser close), this
     104      will equal ``settings.SESSION_COOKIE_AGE``.
     105
     106    * ``get_expiry_date()``
     107
     108      Returns the date this session will expire. For sessions with no custom
     109      expiration (or those set to expire at browser close), this will equal the
     110      date ``settings.SESSION_COOKIE_AGE`` seconds from now.
     111
     112    * ``get_expire_at_browser_close()``
     113
     114      Returns either ``True`` or ``False``, depending on whether this session
     115      will expire when the user's browser is closed.
     116
    78117You can edit ``request.session`` at any point in your view. You can edit it
    79118multiple times.
    80119
     
    217256her browser. Use this if you want people to have to log in every time they open
    218257a browser.
    219258
     259This setting is a global default and can be overwritten by explicitly calling
     260``request.session.set_expiry()`` as described above in
     261`using sessions in views`_.
     262
    220263Clearing the session table
    221264==========================
    222265
Back to Top