Django session 詳解-part II-session

Django中的session是一個高級工具,它可讓用戶存儲我的信息以便在下次訪問網站中使用這些信息。session的基礎仍是cookie,可是它提供了一些更加高級的功能。請看下面的一個例子:python

使用session:

這個例子中實現了一個簡單的計數功能:程序員

def test_count_session(request):
    if 'count' in request.session:
        request.session['count'] += 1
        return HttpResponse('new count=%s' % request.session['count'])
    else:
        request.session['count'] = 1
        return HttpResponse('No count in session. Setting to 1')數據庫

比較session和cookie的使用咱們能夠發現他們有一下幾點不一樣:django

  • session管理更加統一和方便:每一個session中的屬性值可使用查詢以及修改操做。
  • 雖然咱們在例子中只是使用了一個整數的屬性,但實際上session中還能夠包含不少類型的屬性,好比字典屬性,而且它能夠很方便地用Python中的內建方法訪問它們。

雖然咱們在session中設置了一個計數器count,可是若是咱們抓取當前的cookie時會發現,居然沒有count這個屬性!而只是設置了一個看起來彷佛是惟一標識的sesionid,這固然是處於安全方面的考慮。假定用戶不停地訪問一個頁面,好比訪問了10次,那咱們是否是就要對他的計數器+10次呢?顯然這樣作不符合實際狀況,有了這個sessionid,咱們就能夠判斷是不是同一個用戶訪問一個頁面了。安全

Set-Cookie:sessionid=a92d67e44a9b92d7dafca67e507985c0;
           expires=Thu, 07-Jul-2011 04:16:28 GMT;
           Max-Age=1209600;
           Path=/cookie

深刻了解sessionid:

默認狀況下,Django會將session保存在django_session這個表中:session

CREATE TABLE "django_session" (
    "session_key" varchar(40) NOT NULL PRIMARY KEY,
    "session_data" text NOT NULL,
    "expire_date" datetime NOT NULL
);框架

其中的session_key就至關於cookie中保存的sessionid,而session_data就包含了當前session中的屬性。若是想詳細看看咱們上面建立的session的信息,能夠像下面這樣:函數

from django.contrib.sessions.models import Session
#...
sess = Session.objects.get(pk='a92d67e44a9b92d7dafca67e507985c0')
print(sess.session_data)
print(sess.get_decoded()) 工具

 它或許會輸出相似下面的信息:

ZmEyNDVhNTBhMTk2ZmRjNzVlYzQ4NTFjZDk2Y2UwODc3YmVjNWVjZjqAAn1xAVUFY291bnRxAksG
cy4=

{'count': 11}

Django會保存request.session的相關信息到數據庫,而後用戶能夠經過cookie中的sessionid對它進行各類操做。固然這些操做咱們能夠經過Django自帶的session模塊輕鬆操做,從而簡化了程序員的工做。下面咱們來詳細瞭解一下Django中的session。

session中間件:

首先看看Django中的django.http.HttpRequest,瞭解一下它是如何取得session並對其屬性進行操做的。the Django Book中對它有詳細的介紹,咱們這裏就簡單的說一下原理吧 ! Django中的頁面請求的簡單模型就像下面這樣:

django中的簡單流程

視圖方法接受一個httprequest後,對它進行一系列的操做,而後返回一個httpresponse。而中間件增長一些額外的操做:

django中間件視圖

Django的中間件框架就是一些所謂的hook類,它設置在Django項目中的settings中的MIDDLEWARE_CLASSES內。固然您也能夠添加本身的MIDDLEWARE_CLASSES。默認狀況下,django.contrib.sessions.middleware.SessionMiddleware 是自動添加的。查看它的源代碼,咱們能夠發現它實際上就是實現了2個hooks:process_request和process_response。

process_request提取當前cookie中的session KEY(也就是sessionid),其中SESSION_COOKIE_NAME就是咱們說的sessionid。而request.session則包含了"session store"對象。

process_response負責保存"session store"對象並將它返回給客戶端。

session的存儲:

Django中能夠經過設置SESSION_ENGINE屬性來指定後臺引擎來處理session。默認是django.contrib.sessions.backends.db。在Django安裝目錄中的sessions/backends下能夠找到不少其餘的引擎,這裏就再也不贅述。

不論是哪種引擎,它都實現了一個StorageSession類,其中包含了對session的各類操做方法。

爲了理解它的工做原理,假定用戶想訪問request.session,來看看它的工做流程:

  1. Session中間件的process_request實例化一個request.session,並將db.SessionStore附帶session_key保存到構造函數(姑且這麼叫吧,實在想不到好聽的名字)。
  2. SessionStore的構造函數會保存session key以便用戶訪問。
  3. process_request的工做就算完成了,接着session中間件會將request傳給view方法。
  4. SessionBase是一個類字典實例,咱們能夠經過Python內建的字典方法對它進行操做,例如__getitem__。它還有一個頗有用的方法:_get_session(它用到了load方法,load方法是由db.SessionStore來執行的,而不是SessionBase,期間還有一些對數據的編碼工做)

下面來看一個簡單的例子:

def encode(self, session_dict):
    "Returns the given session dictionary pickled and encoded as a string."
    pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
    hash = self._hash(pickled)
    return base64.encodestring(hash + ":" + pickled)

結論:

Django基於最簡單的HTTP request和HTTP response而實現session的使用。但願上面的一些東西能給您帶來一些靈感,若是須要詳細瞭解session,讀者能夠當django官網的session文檔中去找。

# 做者微博:http://weibo.com/amaozhao

相關文章
相關標籤/搜索