How can I determine the age of a开发者_JS百科 session object in django?
OK, here's what I have come up with. Much better. I think this is as cheap as using post_save on a Session object is going to get:
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)
Here's what I ended up doing instead of Thomas' suggestion. Note that I declined to use the receiver decorator so that this will still work pre 1.3.
(This needs serious correction).
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)
I hope that somebody can correct this for me, because I cannot believe that this is the most efficient way to do this.
First and foremost, this adds TWO extra database hits (in the first try: sessioninfo = SessionInfo.objects.get(session=instance)) every time a session is modified.
The first is obviously during the lookup. The second happens when the save occurs, triggering the entire process again.
What to do instead?
you would need to hook the post_init signal coming from django.contrib.sessions.models.Session to be notified of a session start (or end), and then save that info to a model in your own app. e.g.
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
hence when you need to know the age of a session, use session.sessiontimer.age()
. this will return a TimeDelta object representing the age of the session.
精彩评论