子非鱼,安知鱼之乐?

我的程序人生,累并快乐着。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Django:更简单的实现记住密码功能

Posted on 2007-10-29 16:00  Jason Cui  阅读(4556)  评论(3编辑  收藏  举报
Django的设计里,Session的保存是借助Cookie的,Cookie的保存默认有两种周期,浏览器生命周期和14天周期。这两者的选择在settings.py里面的一个参数,设成True就是前者,设成False就是后者。但是,我们通常的需求是用户登录的时候可以选择是否记住登录,如果不选就是前者,如果选中,就使用后者,但是Django却没有留下这个接口。
在我以前的文章里面,是通过直接修改Django的源代码,改了它的sessionMiddleware来解决的,今天在浏览它的google group的时候,终于找到了一个比较正规的方法。其实其原理跟我那个方法是完全一样的,修改sessionMiddleware,让它在设置Cookie之前从当前的session里面读取一个值,看看是否要记住密码,从而控制生成哪一个周期的Cookie。
但是他的做法就比我要高明了,我的做法直接修改了Django的源代码,所以导致每次升级的时候会很麻烦,因为会覆盖以前的修改。但是他的做法是自己重新写了一个sessionMiddleware,基本上,这个文件应该就是直接把原来的拷了出来,然后做修改。只要在settings文件中指定这个middleware的类,让你的项目使用自己的这个就可以了。这样,系统自己的就完全被忽略掉了。
想来想去,还是把代码附上吧,以防万一:
 1from django.conf import settings
 2from django.contrib.sessions.models import Session
 3from django.contrib.sessions.middleware import SessionWrapper
 4from django.utils.cache import patch_vary_headers
 5import datetime
 6
 7class DualSessionMiddleware(object):
 8    """Session middleware that allows you to turn individual browser-length 
 9    sessions into persistent sessions and vice versa.
10    
11    This middleware can be used to implement the common "Remember Me" feature
12    that allows individual users to decide when their session data is discarded.
13    If a user ticks the "Remember Me" check-box on your login form create
14    a persistent session, if they don't then create a browser-length session.
15    
16    This middleware replaces SessionMiddleware, to enable this middleware:
17    - Add this middleware to the MIDDLEWARE_CLASSES setting in settings.py, 
18      replacing the SessionMiddleware entry.
19    - In settings.py add this setting: 
20      PERSISTENT_SESSION_KEY = 'sessionpersistent'
21    - Tweak any other regular SessionMiddleware settings (see the sessions doc),
22      the only session setting that's ignored by this middleware is 
23      SESSION_EXPIRE_AT_BROWSER_CLOSE. 
24      
25    Once this middleware is enabled all sessions will be browser-length by
26    default.
27    
28    To make an individual session persistent simply do this:
29    
30    session[settings.PERSISTENT_SESSION_KEY] = True
31    
32    To make a persistent session browser-length again simply do this:
33    
34    session[settings.PERSISTENT_SESSION_KEY] = False
35    """
36    
37    def process_request(self, request):
38        request.session = SessionWrapper(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None))
39
40    def process_response(self, request, response):
41        # If request.session was modified, or if response.session was set, save
42        # those changes and set a session cookie.
43        patch_vary_headers(response, ('Cookie',))
44        try:
45            modified = request.session.modified
46        except AttributeError:
47            pass
48        else:
49            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
50                session_key = request.session.session_key or Session.objects.get_new_session_key()
51                
52                if not request.session.get(settings.PERSISTENT_SESSION_KEY, False):
53                    # session will expire when the user closes the browser
54                    max_age = None
55                    expires = None
56                else:
57                    max_age = settings.SESSION_COOKIE_AGE
58                    expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
59                
60                new_session = Session.objects.save(session_key, 
61                                                   request.session._session,
62                                                   datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
63                response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
64                                    max_age = max_age, expires = expires, 
65                                    domain = settings.SESSION_COOKIE_DOMAIN,
66                                    secure = settings.SESSION_COOKIE_SECURE or None)
67        return response
68