【问题标题】:django: don't log out when there is an error in view with `request.session.set_exipry`django:当“request.session.set_exipry”出现错误时不要注销
【发布时间】:2012-07-02 23:48:58
【问题描述】:

我目前正在使用 django 开发一个应用程序,每次在渲染视图或模板时出现错误,我的会话都会被注销。这最终很烦人。如何禁用此“功能”?请注意,如果在加载/解析代码时出现错误(例如,如果视图上的装饰器失败),我不会被注销,只有在视图中出现错误时。

编辑:我刚刚测试过,是的,raise Exception 在视图中确实会导致这种情况。

我所有的视图都被一个装饰器包裹着,其中包括:

def needs_base_index_dict(func):
    def wrapper(request, *args, **kwargs):
        request.session.set_expiry(30*60)
        #...

如果我注释掉 set_expiry 行,那么我不会得到这种行为。当我修复错误时,我仍然处于登录状态。如果该行没有被注释掉,那么视图中的任何错误 - 包括 raise Exception() - 都会将会话注销。

【问题讨论】:

  • 我从来没有听说过这个“功能”——你可能想看看为什么会发生这种情况......你是在视图中建议 raise Exception 导致这个吗?动态模板错误也不会导致我出现这种行为(比如文件不存在并且我收到 IOError)
  • 您使用的是哪个会话后端?默认的数据库后端?另外,您是否检查过错误页面的 http 标头中是否存在 cookie?
  • @Jyrsa:我没有明确更改任何内容,所以我认为它使用的是默认值。如何检查?
  • 如果您没有设置任何内容,那么它就是默认值。检查 SESSION_ENGINE。默认值为 django.contrib.sessions.backends.db。请注意上面关于错误页面中 set-cookie 标头的第二个问题。
  • @Jyrsa:我的SESSION_ENGINE 中没有SESSION_ENGINE 变量,所以它肯定是默认值。至于第二个问题,根据谷歌浏览器,cookie存在于请求标头中,但响应标头中没有发送cookie标头。但是没有为非错误页面发送 cookie 标头,或者......好的页面有 Vary:Cookie, Accept-Encoding 而错误页面没有,但是,这是你的意思吗?

标签: python django error-handling


【解决方案1】:

Django 基本上会在每次发生更改时将会话写入数据库。由于您在视图装饰器中更新会话状态,这意味着应该有一个会话写入数据库。

但是,如果您使用的是具有事务管理的数据库,那么当您的视图失败时,您的数据库写入将被回滚。但是,您的会话 cookie 过期时间已在您的浏览器上更新。这意味着您的浏览器会话和存储在服务器上的会话不再匹配。这种不一致会导致会话被丢弃并且您被注销。

这也解释了为什么当您注释掉该行时它可以正常工作。

如果您使用 django 开发服务器,那么您应该能够在控制台中看到您的查询。发生错误时查看会话更新查询是否运行成功。如果没有,您就会知道为什么要退出 :)

这是所需的行为,但如果您想在调试环境中禁用它,则只需在装饰器的相关行上方添加对 DEBUG 的检查。或者,您可以禁用事务管理(不推荐)。

【讨论】:

    【解决方案2】:

    不是原因的答案,而是一种解决方法:

    def needs_base_index_dict(func):
        def wrapper(request, *args, **kwargs):
            #... do the work
            func(*args, **kwargs)
            #... then set the expiry
            request.session.set_expiry(30*60)
    

    【讨论】:

    • 很好,这行得通。除非我猜在渲染模板时出现异常。
    【解决方案3】:

    您在 cmets 中说您在错误页面中也获得了 set-cookie 标头。 会话对象看起来没问题吗?在sessions documentation 中,它说您可以像访问任何其他数据库对象一样访问基于数据库的会话。

    from django.contrib.sessions.models import Session
    s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
    

    如果该会话是针对匿名用户的,那么我愿意称这是一个非常有趣的功能。如果它是一个完全有效的会话,但不知何故在您看来您已不再登录,则在处理会话 cookie 时存在错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多