啟用 Sessions?
Session 是通過 中間件 的方式實現的。
要啟用 Session 的功能,需要完成以下步驟:
修改 MIDDLEWARE_CLASSES 設置,並確定其中包含了 'django.contrib.sessions.middleware.SessionMiddleware' 。``django-admin.py startproject`` 所創建的缺省的 settings.py 就已經激活了 SessionMiddleware 。
將 'django.contrib.sessions' 添加到妳的 INSTALLED_APPS 設置中,並執行 manage.py syncdb 以便安裝用於存儲 Session 數據的表格。
Changed in Django 1.0: 如果妳並未使用數據庫存儲 Session,則此步驟可以忽略;參考 配置 Session 引擎 。
If you don’t want to use sessions, you might as well remove the SessionMiddleware line from MIDDLEWARE_CLASSES and 'django.contrib.sessions' from your INSTALLED_APPS. It’ll save you a small bit of overhead.
配置 Session 引擎?
New in Django 1.0..
缺省情況下,Django 將 Session 存儲在數據庫中 (使用模型 django.contrib.sessions.models.Session)。盡管這很方便,但在某些情況下,把 Session 放在其它的地方速度會更快。因此 Django 允許您通過配置讓它將 Session 數據保存在文件系統或緩沖區中。
使用基於文件的 Session?
要使用基於文件的 Session,請將 SESSION_ENGINE 設置為 "django.contrib.sessions.backends.file" 。
您可能還需要修改 SESSION_FILE_PATH 這壹設置以便控制 Django 存儲 Session 文件的位置,缺省情況下,它使用 tempfile.gettempdir() ,通常是 /tmp 。
使用基於緩沖區的 Session?
要使用 Django 的緩沖區系統來保存 Session,需要將 SESSION_ENGINE 設置為 "django.contrib.sessions.backends.cache" 。您必須確保您已經配置了緩沖區,詳情請參考 緩沖區文檔 。
Note
只有在使用 Memcached 作為緩沖後臺時,才能使用基於緩沖區的 Session。因為以本地內存作為緩沖後臺時,它存儲緩沖數據的時間太短了,這樣直接訪問文件或數據庫的速度,要比通過緩沖區訪問文件或數據庫的速度更快壹些。
在視圖中使用 Session?
在開啟 SessionMiddleware 後,每壹個 HttpRequest 對象 (Django 視圖函數的第壹個參數) 救火有壹個 session 屬性,它是壹個類字典對象。您可以直接對其讀寫。
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.
__contains__(key)
例子: 'fav_color' in request.session
get(key, default=None)
例子: fav_color = request.session.get('fav_color', 'red')
keys()
items()
setdefault()
clear()
New in Django 1.0: setdefault() 和 clear() 是在這個版本新加的。
它還有如下方法:
flush()
New in Django 1.0.
從數據庫中刪除當前的 Session 數據並且重新生成壹個 Session 鍵,並將其發送給瀏覽器。這用於需要確保 Session 數據無法再從用戶瀏覽器訪問時,譬如調用 django.contrib.auth.logout() 時。
set_test_cookie()
設定檢測 Cookie 以檢驗用戶的瀏覽器是否支持 Cookie。因 Cookie 的工作方式,在下壹次用戶請求之前,您都無法得到測試結果。詳情參考下面的 設置檢測 Cookie 。
test_cookie_worked()
判斷用戶的瀏覽器是否收到了檢測 Cookie,並返回 True 或 False 。因 Cookie 的工作方式,您必須在之前的獨立請求中調用 set_test_cookie() 。詳情參考下面的 設置檢測 Cookie 。
delete_test_cookie()
刪除檢測 Cookie,請自己調用此函數以便清除該 Cookie。
set_expiry(value)
New in Django 1.0.
設定 Session 的過期時間。您可以提供下述幾種形式的值:
如果 value 是整形,則它表示的是秒。例如,調用 request.session.set_expiry(300) 會讓 Session 在五分鐘後過期。
如果 value 是 datetime 或 timedelta 對象,則 Session 將會在相應的日期或時間點過期。
如果 value is 0 ,則用戶的 Session 會在瀏覽器關閉時過期。
如果 value is None ,則 Session 會使用全局策略來設定過期時間。
get_expiry_age()
New in Django 1.0.
獲得此 Session 的過期時間。對於沒有自定義過期時間的 Session (或在瀏覽器關閉時過期的 Session),此函數返回值與 settings.SESSION_COOKIE_AGE 相同。
get_expiry_date()
New in Django 1.0.
獲得此 Session 的過期時間點。對於沒有自定義過期時間的 Session (或在瀏覽器關閉時過期的 Session),此函數的返回值等於從現在到時間點 settings.SESSION_COOKIE_AGE 的秒數。
get_expire_at_browser_close()
New in Django 1.0.
返回 Session 是否會在瀏覽器關閉時過期,返回值為 True 或 False 。
您在視圖中的任何位置都可以修改 request.session ,改多少次都行。
Session 對象指南?
直接在 request.session 上使用 Python 字符串作為字典的鍵,這比使用 Session 對象的方法來得更直接。
在 Session 字典中,以下劃線開始的鍵,是保留給 Django 在內部使用的。
不要用壹個新的對象覆蓋 request.session ,也不要訪問或修改它的屬性,它只能作為壹個類字典對象使用。
例子?
這個簡單的視圖在用戶提交了評價信息後,將變量 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!')
這個簡單的視圖讓網站的“用戶”登錄:
def login(request): m = Member.objects.get(username=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.")
...與上面的例子相對應的,下面的例子則讓用戶退出:
def logout(request): try: del request.session['member_id'] except KeyError: pass return HttpResponse("You're logged out.")
實際上標準的 django.contrib.auth.logout() 還會多做壹些事情從而防止因疏忽造成的數據泄露。它會調用 request.session.flush() 函數。我們使用這些例子只是演示如何操作 Session 對象,它可不是壹個完整的 logout() 實現。
設置檢測 Cookie?
為方便起見,Django 提供了壹種簡單的方法來檢測用戶的瀏覽器是否支持 Cookie。只要在壹個請求中調用 request.session.set_test_cookie() 並在後續請求中調用 request.session.test_cookie_worked() 即可。註意千萬不要在同壹次請求中同時調用。
之所以要在兩次請求中調用 set_test_cookie() 和 test_cookie_worked() 是因為 Cookie 的工作模式。當您設定了 Cookie 後,再下壹次請求前,都是沒有辦法知道瀏覽器是否會接收它的。
另外最好在測試完畢後,使用 delete_test_cookie() 清除測試用數據。
以下是壹個典型的例子:
def login(request): if request.method == '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')
在視圖外使用 Session?
New in Django 1.0.
有壹個 API 專門用於在視圖之外操作 Session 數據:
>>> from django.contrib.sessions.backends.db import SessionStore >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) >>> s['last_login'] datetime.datetime(2005, 8, 20, 13, 35, 0) >>> s.save()
如果您使用了 django.contrib.sessions.backends.db 後臺,則每壹個 Session 都是壹個普通的 Django 模型。模型 Session 在文件 django/contrib/sessions/models.py 中定義。由於它是壹個普通的模型,因此您可以使用 Django 的數據庫編程接口直接訪問它:
>>> from django.contrib.sessions.models import Session >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') >>> s.expire_date datetime.datetime(2005, 8, 20, 13, 35, 12)
註意,要獲得 Session 字典,需要調用 get_decoded() ,這是因為字典是以編碼的方式存儲的:
>>> s.session_data 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' >>> s.get_decoded() {'user_id': 42}
Session 是何時存儲的?
缺省情況下,Django 只在 Session 被修改時才會保存它,即只有字典中的值被修改或刪除時:
# Session is modified. request.session['foo'] = 'bar' # Session is modified. del request.session['foo'] # Session is modified. request.session['foo'] = {} # Gotcha: Session is NOT modified, because this alters # request.session['foo'] instead of request.session. request.session['foo']['bar'] = 'baz'
對於在上面的最後壹個,通過顯示地設定 Session 對象的 modified 屬性,可以通知 Session 對象它被修改了:
request.session.modified = True
要改變這種行為,可以將 SESSION_SAVE_EVERY_REQUEST 設定為 True 。如果 SESSION_SAVE_EVERY_REQUEST 是 True ,則 Django 在每壹次獨立的請求之後都會保存 Session。
註意,只有在創建或修改 Session 的時候才會送出 Session Cookie,如果 SESSION_SAVE_EVERY_REQUEST 為 True ,則每次請求都會送出 Cookie。
同樣地,在送出 Cookie 時,它的 expires 部分每次都會被更新。
與瀏覽器同步的 Session 和持久的 Session?
通過設置 SESSION_EXPIRE_AT_BROWSER_CLOSE ,您可以控制 Session 框架使用與瀏覽器同步的 Session 或持久的 Session。
缺省情況下, SESSION_EXPIRE_AT_BROWSER_CLOSE 的值為 False ,這表示 Session Cookie 將會保存在用戶的瀏覽器中,直到超過了 SESSION_COOKIE_AGE 。如果您希望用戶不必在每次關閉瀏覽器後都重新登陸,請使用這種方式。
如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 設定為 True ,則 Django 會使用與瀏覽器同步的 Cookie,即用戶關閉瀏覽器時 Cookie 就會過期。如果您希望用戶每次打開瀏覽器都必須登錄,請使用這種模式。
New in Django 1.0.
這個設置具有全局的缺省值,但可以通過調用 request.session.set_expiry() 為每個 Session 設定獨立的值,相關內容在上述的 在視圖中使用 Session 中有所闡述。
清空 Session 表格?
註意,Session 數據有可能堆積在數據庫表格 django_session 中,Django 不提供 自動清除它們的功能。它把定期清空 Session 數據的任務留給了您。
要理解這個問題,想像壹下用戶使用 Session 時會發生什麽。當用戶登錄,Django 向表格 django_session 中添加壹條記錄。每當 Session 數據變化時,Django 會更新這條記錄。如果用戶手工退出了,Django 會刪除它。但是,如果用戶 沒有 退出,則這條記錄永遠都不會被刪除。
Django 提供了壹個能夠完成清除功能的樣例腳本 django-admin.py cleanup ,它從 Session 表格中刪除那些 expire_date 已經過期的記錄,但是您的應用程序可能會有其它的需求。
設置?
壹些 Django 設置 可以幫助您控制 Session 的行為:
SESSION_ENGINE?
New in Django 1.0.
缺省值: django.contrib.sessions.backends.db
控制 Django 在何處保存 Session 數據,合法的值為:
'django.contrib.sessions.backends.db'
'django.contrib.sessions.backends.file'
'django.contrib.sessions.backends.cache'
詳情請參考 配置 Session 引擎 。
SESSION_FILE_PATH?
New in Django 1.0.
缺省值: /tmp/
如果您使用基於文件的 Session 存儲,則此變量控制著 Django 存儲 Session 數據的目錄。
SESSION_COOKIE_AGE?
缺省值: 1209600 (兩周,以秒表示)
Session Cookie 的過期時間,以秒表示
SESSION_COOKIE_DOMAIN?
缺省值: None
Session Cookie 的域。如果是要設定跨域的 Cookie,可以將其設定為 ".lawrence.com" 的形式,否則請使用 None 。
SESSION_COOKIE_NAME?
缺省值: 'sessionid'
Session 所使用的 Cookie 的名稱,可根據需要設定。
SESSION_COOKIE_SECURE?
缺省值: False
對於 Session Cookie,是否要使用安全模式。如果將此設定為 True ,則 Cookie 將會被標記為“安全”,這種情況下,瀏覽器就需要確定該 Cookie 是否是通過 HTTPS 連接發送的。
SESSION_EXPIRE_AT_BROWSER_CLOSE?
缺省值: False
是否當用戶關閉瀏覽器時就讓 Session 過期。詳情參考上文 與瀏覽器同步的 Session 和持久的Session 。
SESSION_SAVE_EVERY_REQUEST?
缺省值: False
是否在每次請求時都保存 Session 數據。如果此項為 False (缺省值),則 Session 數據只有在它被修改後才會保存,即它的字典值被賦值或刪除時。
技術細節?
Session 字典可以接受任何與 pickle 兼容的 Python 對象,詳情參考 pickle 模塊 。
Session 數據存儲在數據庫表格 django_session 中。
Django 只在需要的時候才發送 Cookie,如果您沒有設定任何的 Session 數據,它不會送出 Cookie。
URL 中的 Session ID?
Django 的 Session 框架是完全基於 Cookie 的,並且它也只能基於 Cookie。它不會像壹些軟件(譬如 PHP)那樣在 Session 不能正常工作時,把 Session ID 放到 URL 中。作出這壹決定是經過深思熟慮的,那種方法不僅使得 URL 很醜陋,並且 Session ID 還有可能通過 “Referer” 頭泄漏出去,從而給網站帶來安全隱患。