2010-11-18 64 views

回答

2

好的,這是我想出的。好多了。我認爲這是作爲使用Session對象post_save便宜是會得到:

from django.db import models 
from people.models import Member 
from django.contrib.sessions.models import Session 
from django.contrib.sessions.backends.db import SessionStore 


from django.db.models import * 
from django.db.models.signals import post_save, pre_delete, post_init 
from datetime import datetime 

class SessionInfo(models.Model): 
    #note: a OneToOneField with the name 'session' has been added as part of the inheritance 
    created = models.DateTimeField(auto_now_add=True) #joined field is auto initialized with creation time 
    session = models.OneToOneField(Session) 
    def age(self): 
     return (datetime.now() - self.created) 


def session_create_listener(instance, **kwargs): 
    store = SessionStore(session_key=instance.session_key) 

    if '_auth_user_id' in store: 
     try: 
      instance.sessioninfo 
     except SessionInfo.DoesNotExist: 
      sessioninfo = SessionInfo(session=instance) 
      sessioninfo.save()   

post_save.connect(session_create_listener, sender=Session) 
+0

撕掉我的回答並標記你的正確。優雅。 – Thomas 2011-01-12 05:12:11

+0

你在開玩笑嗎?你的回答錯了。它不起作用。我對它進行了評論,並等待了一個星期的時間讓你(或其他任何人)修復它。你沒有。我介入並找出問題以及如何解決問題。我發佈了實際工作並沒有引發錯誤的代碼 - 你不認爲這是正確答案的最低要求嗎?儘管您的答案有錯誤,因此不正確,但我仍然投了贊成票,但我不能證明它是正確的,並讓其他觀衆對其應用程序無法正常工作的原因感到頭疼。 – jMyles 2011-01-18 20:35:52

1

您需要掛接來自django.contrib.sessions.models.Session的post_init信號,以通知會話開始(或結束),然後將該信息保存到您自己的應用程序中的模型。例如

from django.contrib.sessions.models import Session 
from django.db.models import * 
from django.db.models.signals import post_init, pre_delete 
from django.dispatch import receiver 
from datetime import datetime 

class SessionTimer(Session): 
    #note: a OneToOneField with the name 'session' has been added as part of the inheritance 
    created = DateTimeField(auto_now_add=True) #joined field is auto initialized with creation time 
    def age(self): 
     return (datetime.now() - self.created) 

@receiver(post_init, sender=Session) 
def session_create_listener(instance, **kwargs): 
    created_session = instance 
    timer_entry = SessionTimer(session=created_session) 
    timer_entry.save() 

@receiver(pre_delete, sender=Session) 
def session_destroy_listener(instance, **kwargs): 
    SessionTimer.objects.get(session=instance).delete() # short version 

因此,當你需要知道一個會話的年齡,使用session.sessiontimer.age()。這將返回一個表示會話年齡的TimeDelta對象。

+0

此代碼不能正常工作,有幾個原因:1)至少進口,「接收器」在錯誤的拼寫裝飾。 2)函數session_create_listener在執行.save()方法時,似乎實際上保存了Session,導致遞歸循環。 3)對象「created_session」結束爲「」,而不是一個Session實例。因此,引發了ValueError。 – jMyles 2011-01-05 19:49:47

+0

完全正確,你是我使用session_create_listener(session,** kwargs)'而不是'session_create_listener(instance,** kwargs)'。現在應該是正確的。 – Thomas 2011-01-09 11:42:41

+0

雖然這對於那些致力於解決方案的人來說是可行和有趣的代碼,但它本身並不是一個。你爲什麼使用post_init而不是post_save?另外,你打算如何處理會導致信號觸發的SessionTimer本身? – jMyles 2011-01-18 20:48:02

0

這是我最終做的,而不是托馬斯的建議。請注意,我拒絕使用接收器裝飾器,以便它在1.3之前仍然有效。

(這需要嚴肅的糾正)。

from django.db import models 
from people.models import Member 
from django.contrib.sessions.models import Session 
from django.contrib.sessions.backends.db import SessionStore 


from django.db.models import * 
from django.db.models.signals import post_save, pre_delete, post_init 
#from django.dispatch import receiver 
from datetime import datetime 

class SessionInfo(models.Model): 
    #note: a OneToOneField with the name 'session' has been added as part of the inheritance 
    created = models.DateTimeField(auto_now_add=True) #joined field is auto initialized with creation time 
    session = models.OneToOneField(Session) 
    def age(self): 
     return (datetime.now() - self.created) 


def session_create_listener(instance, **kwargs): 
    store = SessionStore(session_key=instance.session_key) 

    if '_auth_user_id' in store: 
     try: 
      sessioninfo = SessionInfo.objects.get(session=instance) 
     except SessionInfo.DoesNotExist: 
      sessioninfo = SessionInfo(session=instance) 
      sessioninfo.save() 
      store['anonymous'] = False 
      store.save() 
    else: 
     try: 
      store['anonymous'] 
     except KeyError: 
      store['anonymous'] = True 
      store.save() 

post_save.connect(session_create_listener, sender=Session) 

我希望有人能爲我解決這個問題,因爲我無法相信這是最有效的方法。

首先,每當會話被修改時,這會增加兩個額外的數據庫命中(第一次嘗試:sessioninfo = SessionInfo.objects.get(session = instance))。

第一個顯然是在查找期間。第二次發生保存時,再次觸發整個過程。

怎麼辦?