【问题标题】:Determine the age of a session in django在 django 中确定会话的年龄
【发布时间】:2011-05-11 19:48:28
【问题描述】:

如何确定 django 中会话对象的年龄?

【问题讨论】:

    标签: django session django-views


    【解决方案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 对象。

    【讨论】:

    • 这段代码不起作用,原因如下: 1) 最重要的是,装饰器中的“receiver”拼写错误。 2)函数session_create_listener,在执行.save()方法的时候,好像真的保存了Session,造成了递归循环。 3) 对象“created_session”最终成为“”,而不是 Session 实例。因此,引发了 ValueError。
    • 你说得对,我使用的是 session_create_listener(session, **kwargs)` 而不是 session_create_listener(instance, **kwargs)。现在应该是正确的。
    • 虽然这对于那些致力于解决方案的人来说是可行且有趣的代码,但它本身并不是一个。你为什么使用 post_init 而不是 post_save?另外,您打算如何处理 SessionTimer 本身导致的信号触发?
    【解决方案2】:

    这就是我最终做的,而不是 Thomas 的建议。请注意,我拒绝使用接收器装饰器,因此它在 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))。

    第一个显然是在查找期间。第二次发生在保存发生时,再次触发整个过程。

    该怎么做?

    【讨论】:

      【解决方案3】:

      好的,这就是我想出的。好多了。我认为这与在 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)
      

      【讨论】:

        猜你喜欢
        • 2012-12-15
        • 1970-01-01
        • 1970-01-01
        • 2011-05-05
        • 1970-01-01
        • 1970-01-01
        • 2015-09-10
        • 2023-03-28
        • 1970-01-01
        相关资源
        最近更新 更多