jango.contrib.sessions-SessionBase


摘要 上篇说了django sessions模块的处理流程。session-data的数据管理,都是由一个类负责。这个基类是SessionBase,我们可以继承SessionBase,实现自己对session-data的管理。

SessionBase之所以可当作字典来操作,因为它本身就是对字典的包装。所以需要了解一下python的一些魔法方法。


举个例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class  DictWrapper:  
       def  __init__( self ):  
             self . dict  =  {}  
              
       def  __getitem__( self , key):  
             return  self . dict [key]  
             
       def  __setitem__( self , key, value):  
             self . dict [key]  =  value
             
       def  __delitem__( self , key):
             del  self . dict [key]
             
       def  __contains__( self , key):
         return  key  in  self ._session

__getitem__ 负责获取数据。 

__setitem__负责改变数据。

__delitem__负责删除数据。

__contains__负责判断是否包含这个key。


然后看SessionBase的定义:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class  SessionBase( object ):
     """
     Base class for all Session classes.
     """
     TEST_COOKIE_NAME  =  'testcookie'
     TEST_COOKIE_VALUE  =  'worked'
 
     def  __init__( self , session_key = None ):
         self ._session_key  =  session_key
         self .accessed  =  False
         self .modified  =  False
         self .serializer  =  import_string(settings.SESSION_SERIALIZER)
 
     def  __contains__( self , key):
         return  key  in  self ._session
 
     def  __getitem__( self , key):
         return  self ._session[key]
 
     def  __setitem__( self , key, value):
         self ._session[key]  =  value
         self .modified  =  True
 
     def  __delitem__( self , key):
         del  self ._session[key]
         self .modified  =  True
         
     def  get( self , key, default = None ):
         return  self ._session.get(key, default)
 
     def  pop( self , key,  * args):
         self .modified  =  self .modified  or  key  in  self ._session
         return  self ._session.pop(key,  * args)
         
     def  update( self , dict_):
         self ._session.update(dict_)
         self .modified  =  True
 
     def  has_key( self , key):
         return  key  in  self ._session
 
     def  keys( self ):
         return  self ._session.keys()
 
     def  values( self ):
         return  self ._session.values()
 
     def  items( self ):
         return  self ._session.items()
 
     def  iterkeys( self ):
         return  self ._session.iterkeys()
 
     def  itervalues( self ):
         return  self ._session.itervalues()
 
     def  iteritems( self ):
         return  self ._session.iteritems()

除了上述几个魔法方法, SessionBase还实现了dict的其他的方法。

基本上都是_session的包装。


现在来看看_session的定义:

?
1
_session  =  property (_get_session)

_session的值是_get_session方法返回的。


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def  _get_session( self , no_load = False ):
         """
         Lazily loads session from storage (unless "no_load" is True, when only
         an empty dict is stored) and stores it in the current instance.
         """
         self .accessed  =  True
         try :
             return  self ._session_cache
         except  AttributeError:
             if  self .session_key  is  None  or  no_load:
                 self ._session_cache  =  {}
             else :
                 self ._session_cache  =  self .load()
         return  self ._session_cache


_get_session方法会优先去获取_session_cache这个缓存变量的值,如果没有则调用load方法。

注意self.accessed属性的改变。它会记录是否获取过session。



?
1
2
3
4
5
def  load( self ):
         """
         Loads the session data and returns a dictionary.
         """
         raise  NotImplementedError( 'subclasses of SessionBase must provide a load() method' )

load方法需要子类定义,返回session-data。

一般load实现要注意这种情况,用户第一次登陆是没有_session_cache。注意_get_session方法,它会通过捕获AttributeError异常,判断是否存在_session_cache。如果没有会调用load方法。

所以当用户没有_session_cache的时候,需要返回一个空字典。


注意一下clear的实现。因为执行clear函数时,如果self._session有可能会调用load函数,导致不必要的性能开销。

所以直接复制_session_cache为空。

?
1
2
3
4
5
6
7
def  clear( self ):
         # To avoid unnecessary persistent storage accesses, we set up the
         # internals directly (loading data wastes time, since we are going to
         # set it to an empty dict anyway).
         self ._session_cache  =  {}
         self .accessed  =  True
         self .modified  =  True



因为session和cookie会有一个有效期,以'_session_expiry'存在_session_data里。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def  get_expiry_date( self * * kwargs):
         """Get session the expiry date (as a datetime object).
 
         Optionally, this function accepts `modification` and `expiry` keyword
         arguments specifying the modification and expiry of the session.
         """
         try :
             modification  =  kwargs[ 'modification' ]
         except  KeyError:
             modification  =  timezone.now()
         # Same comment as in get_expiry_age
         try :
             expiry  =  kwargs[ 'expiry' ]
         except  KeyError:
             expiry  =  self .get( '_session_expiry' )
 
         if  isinstance (expiry, datetime):
             return  expiry
         if  not  expiry:    # Checks both None and 0 cases
             expiry  =  settings.SESSION_COOKIE_AGE
         return  modification  +  timedelta(seconds = expiry)

这里注意_session_expiry对应的值,可能是为int,也可能是datetime类型。如果为int,则表示剩下的有效期,以second为单位。如果为datetime类型,则为有效日期,需要计算两者的时间差,也是以second为单位。 


get_expire_at_browser_close方法用来判断session的截至时间是否为关闭浏览器的时间。

当_session_expiry为None并且settings.SESSION_EXPIRE_AT_BROWSER_CLOSE设置为true,

_session_expiry为0,

都会返回true。

?
1
2
3
4
5
6
7
8
9
10
def  get_expire_at_browser_close( self ):
         """
         Returns ``True`` if the session is set to expire when the browser
         closes, and ``False`` if there's an expiry date. Use
         ``get_expiry_date()`` or ``get_expiry_age()`` to find the actual expiry
         date/age, if there is one.
         """
         if  self .get( '_session_expiry' is  None :
             return  settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
         return  self .get( '_session_expiry' = =  0


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值