Django

Code

Ticket #2548: session_middleware.19.diff

File session_middleware.19.diff, 12.2 kB (added by SmileyChris, 8 months ago)

Oh, the last patch also added a slight fix to the db session backend (but I missed a reference to .now() -- session times are now stored in UTC

  • django/contrib/sessions/middleware.py

    old new  
    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_max_age() 
     34                    expires_time = time.time() + max_age 
    3535                    expires = cookie_date(expires_time) 
    3636                # Save the seesion data and refresh the client cookie. 
    3737                request.session.save() 
  • django/contrib/sessions/tests.py

    old new  
    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_max_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_max_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.utcnow() 
     114>>> delta.seconds in (9, 10) 
     115True 
     116>>> age = s.get_max_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.utcnow() 
     123>>> delta.seconds in (9, 10) 
     124True 
     125>>> age = s.get_max_age() 
     126>>> age in (9, 10) 
     127True 
     128 
     129# Custom session fixed expiry date (fixed datetime) 
     130>>> s.set_expiry(datetime.utcnow() + td10) 
     131>>> delta = s.get_expiry_date() - datetime.utcnow() 
     132>>> delta.seconds in (9, 10) 
     133True 
     134>>> age = s.get_max_age() 
     135>>> age in (9, 10) 
     136True 
     137 
     138# Set back to default session age 
     139>>> s.set_expiry(None) 
     140>>> s.get_max_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

    old new  
    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_max_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.utcnow() 
     139        return delta.days * 86400 + delta.seconds 
     140 
     141    def get_expiry_date(self): 
     142        "Returns the expiry date (in UTC)" 
     143        expiry = self.get('_session_expiry', settings.SESSION_COOKIE_AGE) 
     144        if isinstance(expiry, datetime): 
     145            return expiry 
     146        return datetime.utcnow() + timedelta(seconds=expiry) 
     147 
     148    def set_expiry(self, value): 
     149        """ 
     150        Sets a custom expiration for the session. ``value`` can be an integer, a 
     151        Python ``datetime`` or ``timedelta`` object or ``None``. 
     152 
     153        If ``value`` is an integer, the session will expire after that many 
     154        seconds of inactivity. If set to ``0`` then the session will expire on 
     155        browser close. 
     156 
     157        If ``value`` is a ``datetime`` or ``timedelta`` object, the session 
     158        will expire at that specific future time (``datetime`` objects should be 
     159        UTC). 
     160 
     161        If ``value`` is ``None``, the session uses the global session expiry 
     162        policy. 
     163        """ 
     164        if value is None: 
     165            # Remove any custom expiration for this session. 
     166            try: 
     167                del self['_session_expiry'] 
     168            except KeyError: 
     169                pass 
     170            return 
     171        if isinstance(value, timedelta): 
     172            value = datetime.utcnow() + value 
     173        self['_session_expiry'] = value 
     174 
     175    def get_expire_at_browser_close(self): 
     176        if self.get('_session_expiry') is None: 
     177            return settings.SESSION_EXPIRE_AT_BROWSER_CLOSE 
     178        return self.get('_session_expiry') == 0 
     179 
    131180    # Methods that child classes must implement. 
    132181 
    133182    def exists(self, session_key): 
  • django/contrib/sessions/backends/cache.py

    old new  
    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_max_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) 
  • django/contrib/sessions/backends/db.py

    old new  
    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,  
    18                 expire_date__gt=datetime.datetime.now() 
     17                session_key = self.session_key, 
     18                expire_date__gt=datetime.datetime.utcnow() 
    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

    old new  
    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

    old new  
    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()`` 
    107112      Sets a test cookie to determine whether the user's browser supports 
     
    118123    * ``delete_test_cookie()`` 
    119124      Deletes the test cookie. Use this to clean up after yourself. 
    120125 
     126    * ``set_expiry(value)`` 
     127 
     128      **New in Django development version** 
     129 
     130      Sets a custom expiration for the session. 
     131 
     132      If ``value`` is an integer, the session will expire after that many 
     133      seconds of inactivity. If set to ``0`` then the session will expire when 
     134      the user's browser is closed. 
     135 
     136      If ``value`` is a ``datetime`` or ``timedelta`` object, the session will 
     137      expire at that specific time (``datetime`` objects must be in UTC). 
     138 
     139      If ``value`` is ``None``, the session reverts to using the global session 
     140      expiry policy. 
     141 
     142    * ``get_max_age()`` 
     143 
     144      **New in Django development version** 
     145 
     146      Returns the number of seconds until this session expires. For sessions 
     147      with no custom expiration (or those set to expire at browser close), this 
     148      will equal ``settings.SESSION_COOKIE_AGE``. 
     149 
     150    * ``get_expiry_date()`` 
     151 
     152      **New in Django development version** 
     153 
     154      Returns the date this session will expire. For sessions with no custom 
     155      expiration (or those set to expire at browser close), this will equal the 
     156      UTC date ``settings.SESSION_COOKIE_AGE`` seconds from now. 
     157 
     158    * ``get_expire_at_browser_close()`` 
     159 
     160      **New in Django development version** 
     161 
     162      Returns either ``True`` or ``False``, depending on whether this session 
     163      will expire when the user's browser is closed. 
     164 
    121165You can edit ``request.session`` at any point in your view. You can edit it 
    122166multiple times. 
    123167 
     
    278322her browser. Use this if you want people to have to log in every time they open 
    279323a browser. 
    280324 
     325**New in Django development version** 
     326 
     327This setting is a global default and can be overwritten by explicitly calling 
     328``request.session.set_expiry()`` as described above in 
     329`using sessions in views`_. 
     330 
    281331Clearing the session table 
    282332========================== 
    283333