2011-02-27 89 views
17

我想有些東西存儲在數據庫中,和現在用的是當前會話外鍵:從models.py Django的:設置會話和獲取會話密鑰在相同的觀點

class Visited(models.Model): 
    session = models.ForeignKey(Session) 
    page = models.ForeignKey(Page) 
    times_visited = models.PositiveIntegerField() 
    ip_address = models.IPAddressField() 
    date_last_visited = models.DateTimeField() 
    def __unicode__(self): 
     return u'(%s, %s)' % (str(self.session.session_key), str(self.page.name)) 

要使這種模式的新條目我使用以下命令獲取當前會話(在views.py):

Session.objects.get(session_key=request.session.session_key) 

但是,如果這是用戶第一次訪問過該網站,因而不具備上面的代碼會產生一個DoesNotExist錯誤。


我知道,即使是現在的cookie設置,你仍然可以設置會話對象。所以,我能想到的幾個黑客,使這項工作,如:

  • 設置唯一標識符作爲會話對象(除會話密鑰)
  • 暫時存放我想添加到數據數據庫會話對象,並在使用會話之前使用裝飾器函數檢查它是否存在。
  • 只使用會話對象並不會在數據庫中存儲任何內容(這在技術上是可行的,但對於我的實現來說,它將取決於Python字典 - 有幾百個條目 - 至少與數據庫一樣有效排序。)


但我想一個更好的解決方案,我可以住在一起。有什麼常用或很好的解決方案來解決這個問題嗎?或者我甚至在我的模型中正確引用會話?

謝謝你的幫助。

回答

39

request.session是帶有唯一session_key的SessionStore object

只要屬性被訪問,session_key就會被創建。但是,通過調用SessionStore對象的save方法處理視圖(在會話中間件的process_response方法中)後,會話對象本身僅保存到數據庫。

這不是真正的記載,但查看源代碼,我猜你應該建立這樣一個新的會話對象:

if not request.session.exists(request.session.session_key): 
    request.session.create() 

您還可以創建自定義會話中間件,這可以確保你的新會話對象總是可用之前您的任何意見試圖訪問它:

from django.conf import settings 
from django.contrib.sessions.middleware import SessionMiddleware 

class CustomSessionMiddleware(SessionMiddleware): 
    def process_request(self, request): 
     engine = import_module(settings.SESSION_ENGINE) 
     session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None) 
     request.session = engine.SessionStore(session_key) 
     if not request.session.exists(request.session.session_key): 
      request.session.create() 

(當然,你必須通過SESSION_ENIGNE引用裏面的settings.py新的會話中間件)

但要注意 - 這種方法會產生,如果用戶的瀏覽器不支持cookie每個請求一個新的會話對象...

+0

感謝您的優秀解釋它是如何工作(或者說爲什麼它不」工作)。我帶着我提到的第二個「黑客」的變體,爲了簡單起見,如果不是優雅。 – 2011-02-27 13:55:54

+0

我對Django或Python不太熟悉,但我確信這個答案正是我需要的。如果會話ID從客戶端傳遞(我不問),我需要換出會話。我有點困惑,除了'django.contrib.sessions.middleware.SessionMiddleware'還有'SESSION_ENGINE',我是否在'MIDDLEWARE_CLASSES'中引用這個類?當然在'SESSION_ENGINE'中引用它會導致這條線遞歸? 'engine = import_module(settings.SESSION_ENGINE)'。我錯過了這一點嗎? – Steve 2014-08-05 09:21:11

+0

我不認爲'request.session.create()'設置了'Set-Cookie'標題。 – Flimm 2016-01-13 17:03:44