2010-11-18 3 views

ответ

2

ОК, вот что я придумал. Намного лучше. Я думаю, что это так дешево, как с помощью post_save на объекте Session собирается получить:

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

+0

Вы шутите? Ваш ответ был неправильным. Это не работает. Я прокомментировал это и подождал неделю для вас (или кого-либо еще), чтобы исправить это. Ты не. Я вошел и понял проблемы и как их исправить. Я опубликовал код, который действительно работал и не вызывал ошибок - разве вы не думаете, что это минимальное требование правильного ответа? Несмотря на то, что ваш ответ имеет ошибки и, следовательно, является неправильным, я все же проголосовал за него, но я не могу оправдать его правильность и подвергнуть других зрителей тому, как их приложения не работают. – jMyles

1

вам нужно будет подключить сигнал post_init от django.contrib.sessions.models.Session, чтобы получать уведомление о начале (или конце) сеанса, а затем сохранить эту информацию в модели в вашем собственном приложении. например

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(), по-видимому, фактически сохраняет сеанс, вызывая рекурсивный цикл. 3) Объект «created_session» заканчивается « », а не экземпляром сеанса. Таким образом, ValueError возникает. – jMyles

+0

Вы правы, я использовал session_create_listener (session, ** kwargs) 'вместо' session_create_listener (instance, ** kwargs) '. Должно быть правильным сейчас. – Thomas

+0

Хотя это жизнеспособный и интересный код для тех, кто работает над решением, он сам по себе не является. Почему вы используете post_init вместо post_save? Кроме того, что вы собираетесь делать с самим SessionTimer, вызывающим сигнал? – jMyles

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)) при каждом изменении сеанса.

Первый, очевидно, во время поиска. Второе происходит, когда происходит сбой, снова запуская весь процесс.

Что делать вместо этого?

Смежные вопросы