Ticket #2548: session_middleware.21.diff

File session_middleware.21.diff, 13.8 KB (added by SmileyChris, 8 years ago)

Actually, the change to UTC is a bit backwards incompatible and probably not necessary.

  • django/conf/global_settings.py

     
    283283SESSION_COOKIE_SECURE = False                           # Whether the session cookie should be secure (https:// only).
    284284SESSION_COOKIE_PATH = '/'                               # The path of the session cookie.
    285285SESSION_SAVE_EVERY_REQUEST = False                      # Whether to save the session data on every request.
    286 SESSION_EXPIRE_AT_BROWSER_CLOSE = False                 # Whether sessions expire when a user closes his browser.
     286SESSION_EXPIRE_AT_BROWSER_CLOSE = False                 # Whether a user's session cookie expires when they close their browser.
    287287SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # The module to store session data
    288288SESSION_FILE_PATH = '/tmp/'                             # Directory to store session files if using the file session module
    289289
  • django/contrib/sessions/middleware.py

     
    2626            if accessed:
    2727                patch_vary_headers(response, ('Cookie',))
    2828            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
    29                 if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
     29                if request.session.get_expire_at_browser_close():
    3030                    max_age = None
    3131                    expires = None
    3232                else:
    33                     max_age = settings.SESSION_COOKIE_AGE
    34                     expires_time = time.time() + settings.SESSION_COOKIE_AGE
     33                    max_age = request.session.get_expire_age()
     34                    expires_time = time.time() + max_age
    3535                    expires = cookie_date(expires_time)
    36                 # Save the seesion data and refresh the client cookie.
     36                # Save the session data and refresh the client cookie.
    3737                request.session.save()
    3838                response.set_cookie(settings.SESSION_COOKIE_NAME,
    3939                        request.session.session_key, max_age=max_age,
  • django/contrib/sessions/tests.py

     
    8888
    8989>>> s.pop('some key', 'does not exist')
    9090'does not exist'
     91
     92#########################
     93# Custom session expiry #
     94#########################
     95
     96>>> from django.conf import settings
     97>>> from datetime import datetime, timedelta
     98
     99>>> td10 = timedelta(seconds=10)
     100
     101# A normal session has a max age equal to settings
     102>>> s.get_expiry_age() == settings.SESSION_COOKIE_AGE
     103True
     104
     105# So does a custom session with an idle expiration time of 0 (but it'll expire
     106# at browser close)
     107>>> s.set_expiry(0)
     108>>> s.get_expiry_age() == settings.SESSION_COOKIE_AGE
     109True
     110
     111# Custom session idle expiration time
     112>>> s.set_expiry(10)
     113>>> delta = s.get_expiry_date() - datetime.now()
     114>>> delta.seconds in (9, 10)
     115True
     116>>> age = s.get_expiry_age()
     117>>> age in (9, 10)
     118True
     119
     120# Custom session fixed expiry date (timedelta)
     121>>> s.set_expiry(td10)
     122>>> delta = s.get_expiry_date() - datetime.now()
     123>>> delta.seconds in (9, 10)
     124True
     125>>> age = s.get_expiry_age()
     126>>> age in (9, 10)
     127True
     128
     129# Custom session fixed expiry date (fixed datetime)
     130>>> s.set_expiry(datetime.now() + td10)
     131>>> delta = s.get_expiry_date() - datetime.now()
     132>>> delta.seconds in (9, 10)
     133True
     134>>> age = s.get_expiry_age()
     135>>> age in (9, 10)
     136True
     137
     138# Set back to default session age
     139>>> s.set_expiry(None)
     140>>> s.get_expiry_age() == settings.SESSION_COOKIE_AGE
     141True
     142
     143# Allow to set back to default session age even if no alternate has been set
     144>>> s.set_expiry(None)
     145
     146
     147# We're changing the setting then reverting back to the original setting at the
     148# end of these tests.
     149>>> original_expire_at_browser_close = settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
     150>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False
     151
     152# Custom session age
     153>>> s.set_expiry(10)
     154>>> s.get_expire_at_browser_close()
     155False
     156
     157# Custom expire-at-browser-close
     158>>> s.set_expiry(0)
     159>>> s.get_expire_at_browser_close()
     160True
     161
     162# Default session age
     163>>> s.set_expiry(None)
     164>>> s.get_expire_at_browser_close()
     165False
     166
     167>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = True
     168
     169# Custom session age
     170>>> s.set_expiry(10)
     171>>> s.get_expire_at_browser_close()
     172False
     173
     174# Custom expire-at-browser-close
     175>>> s.set_expiry(0)
     176>>> s.get_expire_at_browser_close()
     177True
     178
     179# Default session age
     180>>> s.set_expiry(None)
     181>>> s.get_expire_at_browser_close()
     182True
     183
     184>>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = original_expire_at_browser_close
    91185"""
    92186
    93187if __name__ == '__main__':
  • django/contrib/sessions/backends/base.py

     
    44import random
    55import sys
    66import time
     7from datetime import datetime, timedelta
    78from django.conf import settings
    89from django.core.exceptions import SuspiciousOperation
    910
     
    128129
    129130    _session = property(_get_session)
    130131
     132    def get_expiry_age(self):
     133        expiry = self.get('_session_expiry')
     134        if not expiry:   # Checks both None and 0 cases
     135            return settings.SESSION_COOKIE_AGE
     136        if not isinstance(expiry, datetime):
     137            return expiry
     138        delta = expiry - datetime.now()
     139        return delta.days * 86400 + delta.seconds
     140
     141    def get_expiry_date(self):
     142        "Returns the expiry date"
     143        expiry = self.get('_session_expiry')
     144        if isinstance(expiry, datetime):
     145            return expiry
     146        if not expiry:   # Checks both None and 0 cases
     147            expiry = settings.SESSION_COOKIE_AGE
     148        return datetime.now() + timedelta(seconds=expiry)
     149
     150    def set_expiry(self, value):
     151        """
     152        Sets a custom expiration for the session. ``value`` can be an integer, a
     153        Python ``datetime`` or ``timedelta`` object or ``None``.
     154
     155        If ``value`` is an integer, the session will expire after that many
     156        seconds of inactivity. If set to ``0`` then the session will expire on
     157        browser close.
     158
     159        If ``value`` is a ``datetime`` or ``timedelta`` object, the session
     160        will expire at that specific future time.
     161
     162        If ``value`` is ``None``, the session uses the global session expiry
     163        policy.
     164        """
     165        if value is None:
     166            # Remove any custom expiration for this session.
     167            try:
     168                del self['_session_expiry']
     169            except KeyError:
     170                pass
     171            return
     172        if isinstance(value, timedelta):
     173            value = datetime.now() + value
     174        self['_session_expiry'] = value
     175
     176    def get_expire_at_browser_close(self):
     177        if self.get('_session_expiry') is None:
     178            return settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
     179        return self.get('_session_expiry') == 0
     180
    131181    # Methods that child classes must implement.
    132182
    133183    def exists(self, session_key):
  • django/contrib/sessions/backends/cache.py

     
    44
    55class SessionStore(SessionBase):
    66    """
    7     A cache-based session store. 
     7    A cache-based session store.
    88    """
    99    def __init__(self, session_key=None):
    1010        self._cache = cache
    1111        super(SessionStore, self).__init__(session_key)
    12        
     12
    1313    def load(self):
    1414        session_data = self._cache.get(self.session_key)
    1515        return session_data or {}
    1616
    1717    def save(self):
    18         self._cache.set(self.session_key, self._session, settings.SESSION_COOKIE_AGE)
     18        self._cache.set(self.session_key, self._session, self.get_expiry_age())
    1919
    2020    def exists(self, session_key):
    2121        if self._cache.get(session_key):
    2222            return True
    2323        return False
    24        
     24
    2525    def delete(self, session_key):
    2626        self._cache.delete(session_key)
     27 No newline at end of file
  • django/contrib/sessions/backends/db.py

     
    1010    """
    1111    def __init__(self, session_key=None):
    1212        super(SessionStore, self).__init__(session_key)
    13    
     13
    1414    def load(self):
    1515        try:
    1616            s = Session.objects.get(
    17                 session_key = self.session_key, 
     17                session_key = self.session_key,
    1818                expire_date__gt=datetime.datetime.now()
    1919            )
    2020            return self.decode(s.session_data)
    2121        except (Session.DoesNotExist, SuspiciousOperation):
    22            
     22
    2323            # Create a new session_key for extra security.
    2424            self.session_key = self._get_new_session_key()
    2525            self._session_cache = {}
     
    2727            # Save immediately to minimize collision
    2828            self.save()
    2929            return {}
    30            
     30
    3131    def exists(self, session_key):
    3232        try:
    3333            Session.objects.get(session_key=session_key)
    3434        except Session.DoesNotExist:
    3535            return False
    3636        return True
    37            
     37
    3838    def save(self):
    3939        Session.objects.create(
    4040            session_key = self.session_key,
    4141            session_data = self.encode(self._session),
    42             expire_date = datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)
     42            expire_date = self.get_expiry_date()
    4343        )
    44    
     44
    4545    def delete(self, session_key):
    4646        try:
    4747            Session.objects.get(session_key=session_key).delete()
  • AUTHORS

     
    327327    tstromberg@google.com
    328328    Makoto Tsuyuki <mtsuyuki@gmail.com>
    329329    tt@gurgle.no
    330     Amit Upadhyay
     330    Amit Upadhyay <http://www.amitu.com/blog/>
    331331    Geert Vanderkelen
    332332    I.S. van Oostveen <v.oostveen@idca.nl>
    333333    viestards.lists@gmail.com
  • docs/sessions.txt

     
    8080It implements the following standard dictionary methods:
    8181
    8282    * ``__getitem__(key)``
     83
    8384      Example: ``fav_color = request.session['fav_color']``
    8485
    8586    * ``__setitem__(key, value)``
     87
    8688      Example: ``request.session['fav_color'] = 'blue'``
    8789
    8890    * ``__delitem__(key)``
     91
    8992      Example: ``del request.session['fav_color']``. This raises ``KeyError``
    9093      if the given ``key`` isn't already in the session.
    9194
    9295    * ``__contains__(key)``
     96
    9397      Example: ``'fav_color' in request.session``
    9498
    9599    * ``get(key, default=None)``
     100
    96101      Example: ``fav_color = request.session.get('fav_color', 'red')``
    97102
    98103    * ``keys()``
     
    101106
    102107    * ``setdefault()`` (**New in Django development version**)
    103108
    104 It also has these three methods:
     109It also has these methods:
    105110
    106111    * ``set_test_cookie()``
     112
    107113      Sets a test cookie to determine whether the user's browser supports
    108114      cookies. Due to the way cookies work, you won't be able to test this
    109115      until the user's next page request. See "Setting test cookies" below for
    110116      more information.
    111117
    112118    * ``test_cookie_worked()``
     119
    113120      Returns either ``True`` or ``False``, depending on whether the user's
    114121      browser accepted the test cookie. Due to the way cookies work, you'll
    115122      have to call ``set_test_cookie()`` on a previous, separate page request.
    116123      See "Setting test cookies" below for more information.
    117124
    118125    * ``delete_test_cookie()``
     126
    119127      Deletes the test cookie. Use this to clean up after yourself.
    120128
     129    * ``set_expiry(value)``
     130
     131      **New in Django development version**
     132
     133      Sets a custom expiration for the session.
     134
     135      If ``value`` is an integer, the session will expire after that many
     136      seconds of inactivity. If set to ``0`` then the user's session cookie will
     137      expire when their browser is closed.
     138
     139      If ``value`` is a ``datetime`` or ``timedelta`` object, the session will
     140      expire at that specific time.
     141
     142      If ``value`` is ``None``, the session reverts to using the global session
     143      expiry policy.
     144
     145    * ``get_expiry_age()``
     146
     147      **New in Django development version**
     148
     149      Returns the number of seconds until this session expires. For sessions
     150      with no custom expiration (or those set to expire at browser close), this
     151      will equal ``settings.SESSION_COOKIE_AGE``.
     152
     153    * ``get_expiry_date()``
     154
     155      **New in Django development version**
     156
     157      Returns the date this session will expire. For sessions with no custom
     158      expiration (or those set to expire at browser close), this will equal the
     159      date ``settings.SESSION_COOKIE_AGE`` seconds from now.
     160
     161    * ``get_expire_at_browser_close()``
     162
     163      **New in Django development version**
     164
     165      Returns either ``True`` or ``False``, depending on whether the user's
     166      session cookie will expire when their browser is closed.
     167
    121168You can edit ``request.session`` at any point in your view. You can edit it
    122169multiple times.
    123170
     
    278325her browser. Use this if you want people to have to log in every time they open
    279326a browser.
    280327
     328**New in Django development version**
     329
     330This setting is a global default and can be overwritten at a per-session level
     331by explicitly calling ``request.session.set_expiry()`` as described above in
     332`using sessions in views`_.
     333
    281334Clearing the session table
    282335==========================
    283336
Back to Top