Django:在同一视图中设置会话并获取会话密钥

Jon*_*Cox 20 django django-models django-sessions

我想将一些东西存储在数据库中,并使用当前会话作为外键:来自models.py

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))
Run Code Online (Sandbox Code Playgroud)

要为此模型创建一个新条目,我使用以下内容来获取当前会话(在views.py中):

Session.objects.get(session_key=request.session.session_key)
Run Code Online (Sandbox Code Playgroud)

但是,如果这是用户第一次访问该站点,因此尚未设置cookie,则上述代码将产生DoesNotExist错误.


我知道即使现在有cookie设置,你仍然可以设置会话对象.所以我可以想到一些黑客来完成这项工作,例如:

  • 将唯一标识符设置为会话对象(除了会话密钥)
  • 暂时将我希望添加到数据库中的数据存储到会话对象中,并使用装饰器函数在使用会话之前检查它是否存在.
  • 只使用会话对象而不是在数据库中存储任何东西(这在技术上是可行的,但对于我的实现,它将依赖于Python字典 - 有几百个条目 - 至少与排序等数据库一样有效.)


但我想要一个更好的解决方案,我可以忍受.这个问题是否有任何普遍使用或良好的解决方案?或者我甚至在我的模型中正确引用会话?

谢谢您的帮助.

cod*_*aft 46

request.session是具有唯一session_key 的 SessionStore对象.

访问该属性后立即创建session_key.但是,会话对象本身仅在通过调用SessionStore对象的save方法处理视图(在会话中间件的process_response方法中)后保存到数据库中.

它没有真正记录,但查看源代码我猜你应该创建一个像这样的新会话对象:

if not request.session.exists(request.session.session_key):
    request.session.create() 
Run Code Online (Sandbox Code Playgroud)

您还可以创建自定义会话中间件,以确保在您的任何视图尝试访问它之前,您的新会话对象始终可用:

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() 
Run Code Online (Sandbox Code Playgroud)

(当然你必须通过你内部的SESSION_ENGINE引用你的新会话中间件settings.py)

但要注意 - 如果用户的浏览器不支持cookie,这种方法将为每个请求生成一个新的会话对象...