作者: Django 团队 译者: 翻译开始日期: 2006-04-27 修订日期: 2006-04-27 原文版本: 2744
Django 完全支持匿名 session. session 框架允许每一个用户保存并取回数据. 它抽象发送及接收 cookies 并在服务器端保存数据. Cookie 中包含一个 session ID – 并不是数据本身.
启用 sessions默认情况下, Session 功能就是启用的.
通过修改 MIDDLEWARE_CLASSES 设置你可以手工启用或关闭 session 功能.要激活 session 功能, 你要保证 MIDDLEWARE_CLASSES 包含 "django.contrib.sessions.middleware.SessionMiddleware".
如果你不想使用 sessions, 在 MIDDLEWARE_CLASSES 中移除 SessionMiddleware 行. 这会为你的系统减少一点负载.
在 views 中使用 session每一个 HttpRequest 对象 – 即任意 Django view 函数的第一个参数 – 拥有一个 session 属性, 该属性是一个行为类似字典的可读写对象.
它实现了以下标准字典方法:
- contains(key) 例子: ‘fav_color’ in request.session
- getitem(key) 例子: fav_color = request.session[‘fav_color’]
- setitem(key, value) 例子: request.session[‘fav_color’] = ‘blue’
- delitem(key) 例子: del request.session[‘fav_color’]. This raises KeyError if the given key isn’t already in the session.
- get(key, default=None) 例子: fav_color = request.session.get(‘fav_color’, ‘red’)
- keys()
- items()
它还拥有以下三个方法:
- set_test_cookie() 设置一个测试 cookie 以判断用户浏览器是否支持 cookie. 由于 cookie 的工作方式, 除非得到用户的下一请求页面,你无法知道用户浏览器是否支持cookie. 阅读阅读下文中的 "Setting test cookies" 可以得到更多信息.
- test_cookie_worked() 根据用户浏览器是否接受测试cookie 返回 True 或 False, 由于cookie 特殊的工作方式, 你必须在前一个独立的页面请求中调用 set_test_cookie() .阅读下文中的 "Setting test cookies" 可以得到更多信息.
- delete_test_cookie() 删除测试 cookie. 可以用它来清理你的 cookie.
在你的 view 的任何部分都可以编辑 request.session , 你也可以在 view 中多次修改它的值.
Session 对象指南几个例子
- 使用常规的 Python 字符串作为字典的 request.session 的 key. 这是一个使用惯例而不是硬性规定.
- 下划线开头的 Session key 被保留为由 Django 内部使用.
- 不要用一个新对象覆盖 request.session , 也不要访问或设置它的属性. 你应该一直把它当成一个字典来使用.
下面这个极为简单的 view 在用户发表了一个评论之后将 has_commented 变量的值设置为 True . 它只允许用户发表一次评论:
def post_comment(request, new_comment):if request.session.get(‘has_commented’, False):
return HttpResponse("You’ve already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session[‘has_commented’] = True
return HttpResponse(‘Thanks for your comment!’)
下面这个 view 则用于一个站点的用户登录:
def login(request):m = members.get_object(username__exact=request.POST[‘username’])
if m.password == request.POST[‘password’]:
request.session[‘member_id’] = m.id
return HttpResponse("You’re logged in.")
else:
return HttpResponse("Your username and password didn’t match.")
…这一个则根据上面的 login() 用于用户登出:
def logout(request):try:
del request.session[‘member_id’]
except KeyError:
pass
return HttpResponse("You’re logged out.")设置测试 cookie
方便起见, Django 提供了一个简单有效的方式来测试用户浏览器是否接受 cookie .在一个 view 中调用 request.session.set_test_cookie() 然后在后面的view中调用 request.session.test_cookie_worked() – 注意不能是同一个 view 的两次调用.
这种看似笨拙将 set_test_cookie() 及 test_cookie_worked() 分成两步执行的方法是不得以的. 当你设置一个 cookie 以后,在浏览器的下一次请求之前,你无法知道浏览器是否接受了它.
在测试完毕之后, 及时使用 delete_test_cookie() 清理掉测试 cookie 是一个好习惯.
下面是一个典型应用的例子:
def login(request):if request.POST:
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You’re logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render_to_response(‘foo/login_form.html’)在 view 之外使用 session
在系统内部, 每一个 session 都是一个 Django model. Session model 定义在 django/contrib/sessions/models.py. 因为它就是一个普通的 model ,你可以使用常规的 Django 数据库 API 访问 sessions.:
>>> from django.contrib.sessions.models import Session>>> s = Session.objects.get_object(pk=‘2b1189a188b44ad18c35e113ac6ceead’)
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
注意你需要调用 get_decoded() 来得到 session 字典. 这一步是必须的, 因为这个字典是被编码以后存储的:
>>> s.session_data‘KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj…’
>>> s.get_decoded()
{‘user_id’: 42}何时保存 session
默认情况下, Django 只在 session 被修改时保存 session 到数据库 – 也就是 session 被赋值或删除时:
# Session被修改request.session[‘foo’] = ‘bar’
# Session被修改
del request.session[‘foo’]
# Session被修改
request.session[‘foo’] = {}
# Gotcha: Session 未被修改, 因为它改变的是
# request.session[‘foo’] 而不是 request.session.
request.session[‘foo’][‘bar’] = ‘baz’
要改变这种默认行为, 将 SESSION_SAVE_EVERY_REQUEST 设置为 True. 若 SESSION_SAVE_EVERY_REQUEST 为 True, Django 会在发生任何一次单独的请求时保存 session 到数据库.
注意 session cookie 仅当一个 session 变量被创建或修改时才将其发送到客户端.如果 SESSION_SAVE_EVERY_REQUEST 为 True, session cookie 就会在任何一次请求时被发送.
类似的, 一个 session cookie 的 expires 部分在发送 session cookie 时也将自动更新.
设置几个 Django settings 允许你控制 session 的行为:
SESSION_COOKIE_AGE默认值: 1209600 (2 周, 以秒计)
session cookie 的有效期, 以秒计.
SESSION_COOKIE_DOMAIN默认值: None
使用 session cookie 的域. 如果要 session cookie 跨域工作, 将它设置为类似 ".lawrence.com" , 否则就设置为 None (标准cookie工作方式).
SESSION_COOKIE_NAME默认值: ‘sessionid’
session cookie 的名字. 你可以任意设置.
SESSION_SAVE_EVERY_REQUEST默认值: False
是否每次请求都保存 session 数据. 若值为 False (默认), 则仅当 session 内容改变时才保存 – 也就是, 当任何字典值被赋值或删除时.
技术细节URL 中的 Session ID
- session 字典接受任何 pickleable Python 对象. 参阅 the pickle module 了解更多信息.
- Session 数据被保存在数据库中的 django_session 表中.
- Django 仅在需要时才发送 cookie . 如果你没有设置任何 session 数据, 它就不会发送任何 cookie.
Django sessions 框架基于 cookie, 它完整并且独立. 它不会将 session id 放到 url 中作为最后的手段(PHP是那样). 我们故意让它这样(不使用url), 不仅仅是因为那种行为使得 url 很丑陋, 主要是因为那样会使得你的站点易被攻击.(通过 "Referer"头窃取 session-ID).
...