13

我似乎和这个问题有同样的问题:Django logout problem

我的有点奇怪,它可以在 google chrome 中运行……但在 Firefox 中不行……

这是我的注销功能:(在views.py中)

def my_logout(request):
    logger.debug("Logout called by user")
    try:
        # Here I do some custom stuff, like logging this action in a database and so on
        # For this question it shouldn't matter... because in a try catch
        # so whatever goes wrong here, logging out should work anyway
    except Exception, e:
        logger.info("Logging logout action error: %s" % e)
    logout(request)
    return HttpResponseRedirect("/")

在 settings.py 我有:

LOGIN_URL = '/desktop/login/'
LOGOUT_URL = '/desktop/logout/'
LOGIN_REDIRECT_URL = '/'

在应用程序iamapps 的urls.py 中(包括在项目url 中为/desktop/):

url(r'^login/$', 'iamapps.views.my_login', name='iamapps.login'),
url(r'^logout/$', 'iamapps.views.my_logout', name='iamapps.logout'),

更多信息:

  • django 1.4.3(刚刚从 1.3 更新到 1.4 ....)
  • 蟒蛇2.7
  • 适用于 Chrome 但不适用于 Firefox 17.0.1、Linux

它在 google chrome 中工作但在 firefox 中不工作的事实最让我困惑。似乎它与firefox不断记住用户登录有关......

编辑: 我的管道坏了……但我似乎不是在注销时得到它……而是在注销后进入主视图……

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 86, in run
    self.finish_response()
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 127, in finish_response
    self.write(data)
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 210, in write
    self.send_headers()
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 268, in send_headers
    self.send_preamble()
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 192, in send_preamble
    'Date: %s\r\n' % format_date_time(time.time())
  File "/usr/lib/python2.7/socket.py", line 324, in write
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 58684)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 582, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/media/storage/django/sites/iamfloraservice/parts/django/django/core/servers/basehttp.py", line 139, in __init__
    super(WSGIRequestHandler, self).__init__(*args, **kwargs)
  File "/usr/lib/python2.7/SocketServer.py", line 641, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 694, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
[24/Dec/2012 14:33:25] "GET / HTTP/1.1" 200 48247

编辑 2 它在注销并被重定向后进入此视图:

def home(request, template='iamfloraservice/home.html'):

    logger.debug("Home view called by user %s" % request.user)
    return render_to_response(template,{},context_instance=RequestContext(request))

我认为请求重定向到这个视图会导致问题....在日志中它仍然是用户'michel'(因为视图使用来自重定向的请求,并且有用户michel)......但是.. . 用户 michel 正在同时注销....

编辑 3

由于建议是由于记录器。取消记录日志并没有帮助它是默认记录器:

import logging
logger = logging.getLogger(__name__)

编辑 4 (30-12-2012)

我的注销来自一个主窗口,当用户登录时我会显示一个注销链接,如果用户注销,我会显示一个登录链接。它还包含一个工具栏,根据用户及其组成员身份填充哪些工具。

我认为问题是,它正在重新加载这个主窗口,而缓存和它的请求中的用户还没有被清除。不知何故,Chrome 知道如何处理这个问题,而 Firefox 会导致管道损坏错误。在浏览器中手动清除缓存会导致重新加载后的正确视图....

一个解决方案可能是重定向到一个没有任何包含用户的页面......或者找出在我自己的正确时刻清除缓存......

这个问题描述的可能相同......但我不能指望用户在浏览器中做任何事情只是为了注销?请参阅django 1.4 将 GET 缓存到 /login/

编辑 5 (31-12-2012)

似乎这是一个缓存问题....但不知道如何解决这个问题。

这些是我的缓存设置:

if not DEBUG:
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }
else:
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
        }
    }

但我也试过没有 dummycache

编辑 6(2013 年 1 月 4 日)仍然没有解决方案....我将注销方式更改为 django 方式,现在我正在使用信号...请参阅下面的我自己的答案。

但它仍然给出了brokenpipe错误,导致firefox停止注销。这不是缓存问题。如果我转到另一个页面,或者更糟糕的是......管理页面。我仍然登录。注销的唯一方法是通过管理页面上的注销......如果它不是管理员用户......没有办法让我在 firefox 浏览器上注销。

使用管理界面注销时,信号工作正常...

我通过关闭信号进行了检查....仍然无法在Firefox中注销。

结论:回到主页()是导致问题的原因。

编辑 7(2013 年 1 月 4 日)我为测试制作了一个简单的注销视图,这个模板:

<html>
<head>
<title>
Logged out
</title>
</head>
<body>
You are succesfully logged out.<br>
<br>
<a href="/">Go back to the main page</a>
or<br>
<a href="/desktop/login/?next=/">log in again</a>
</body>
</html>

和注销的视图:

class LoggedOutView(TemplateView):
    template_name = "iamapps/logged_out.html"

并将网址更改为:

url(r'^logout/$', 'django.contrib.auth.views.logout',  {'next_page': '/desktop/loggedout/'}, name='iamapps.logout'),
#url(r'^logout/$', 'django.contrib.auth.views.logout_then_login',  name='iamapps.logout'),
url(r'^loggedout/$', LoggedOutView.as_view(),name='iamapps.loggedout'),

而且,为了简单起见……我已经关闭了信号。

它仍然无法在 Firefox 中运行......但它在 chrome 中运行

在 Firefox 中,它不会转到已注销的页面

4

5 回答 5

13

我通常只使用贡献视图来注销用户。只需将其添加到您的根urls.py文件中:

# Would be nice to use settings.LOGIN_URL for `next_page` here, too
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/login'}),

你会很高兴的。

快乐的姜戈。

于 2012-12-25T17:03:13.213 回答
3

最后我完全切换到几乎回到 django 默认值...使用:

在views.py中:

from django.contrib.auth.forms import AuthenticationForm
from django.views.generic.edit import FormView

class LoginView(FormView):
    """
    This is a class based version of django.contrib.auth.views.login.


    """
    form_class = AuthenticationForm
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'iamapps/login.html'


    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, *args, **kwargs):
        return super(LoginView, self).dispatch(*args, **kwargs)

    def form_valid(self, form):
        """
        The user has provided valid credentials (this was checked in AuthenticationForm.is_valid()). So now we
        can check the test cookie stuff and log him in.
        """
        self.check_and_delete_test_cookie()
        login(self.request, form.get_user())
        return super(LoginView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(LoginView, self).get_context_data(**kwargs)
        apps_settings=iamapps_settings()
        if apps_settings[LOGON_BASE_APP_NAME]:
            self.extend_template="%s/base.html" % apps_settings[LOGON_BASE_APP_NAME]
        else:
            self.extend_template="iamapps/base.html"
        context['extend_template']=self.extend_template
        return context    

    def form_invalid(self, form):
        """
        The user has provided invalid credentials (this was checked in AuthenticationForm.is_valid()). So now we
        set the test cookie again and re-render the form with errors.
        """
        self.set_test_cookie()
        return super(LoginView, self).form_invalid(form)

    def get_success_url(self):
        if self.success_url:
            redirect_to = self.success_url
        else:
            redirect_to = self.request.REQUEST.get(self.redirect_field_name, '')

        netloc = urlparse.urlparse(redirect_to)[1]
        if not redirect_to:
            redirect_to = settings.LOGIN_REDIRECT_URL
        # Security check -- don't allow redirection to a different host.
        elif netloc and netloc != self.request.get_host():
            redirect_to = settings.LOGIN_REDIRECT_URL
        return redirect_to

    def set_test_cookie(self):
        self.request.session.set_test_cookie()

    def check_and_delete_test_cookie(self):
        if self.request.session.test_cookie_worked():
            self.request.session.delete_test_cookie()
            return True
        return False

    def get(self, request, *args, **kwargs):
        """
        Same as django.views.generic.edit.ProcessFormView.get(), but adds test cookie stuff
        """
        self.set_test_cookie()
        return super(LoginView, self).get(request, *args, **kwargs)

和网址:

url(r'^login/$', LoginView.as_view(), name='login'),

这解决了我所有的麻烦......关于登录和注销......

登录和注销信号工作正常:

from django.contrib.auth.signals import user_logged_out, user_logged_in

# Note, these login and logout signals are registered in imamstats views
def iam_logged_out_actions(sender, user, request, **kwargs):
    try:
        # ... do my logging out actiosn (stats etc.)
    except Exception, e:
        logger.error("Logging logout action error: %s" % e)

# Note, these login and logout signals are registered in imamstats views
def iam_logged_in_actions(sender, user, request, **kwargs):
    try:
        # ... do my log in stats etc. things
    except Exception, e:
        logger.error("Logging login action error: %s" % e)
于 2014-02-12T08:32:40.460 回答
2

浏览到stackoverflow ...(又搜索了一次)

我找到了这个:.. 参见Django 中的 django.contrib.auth.logout ..

但更糟糕的是......我发现这......很惊讶......但解释了一切: Django,Logout_URL doesn't redirect well

我发现这是一个无法修复的错误 (@##$%%) 不允许在平安夜诅咒....

所以做我的自定义东西的解决方案是在信号中,而不是使用我自己的视图。执行默认视图和重定向...并使用此文档创建信号.. https://docs.djangoproject.com/en/dev/topics/auth/#login-and-logout-signals

添加信号很容易,我把它放在我的主应用程序(iamapps)的models.py中:

import logging
from django.contrib.auth.signals import user_logged_out
from django.contrib.auth.signals import user_logged_in
logger = logging.getLogger(__name__)

def iam_logged_out_actions(sender, user, request, **kwargs):
    #whatever...
    logger.debug("Logging out: user = %s" % user)

user_logged_out.connect(iam_logged_out_actions)

def iam_logged_in_actions(sender, user, request, **kwargs):
    #whatever...
    logger.debug("Logging in: user = %s" % user)

user_logged_in.connect(iam_logged_in_actions)

这有效....但是它不能解决我认为可能导致注销失败的损坏管道...所以在 Firefox 中注销仍然失败...在 chrome 中它可以工作...从 django 注销管理页面在 Firefox 中工作。信号还有另一个优点:同样从管理界面中注销,信号被调用......

为了注销,我现在使用这个 urls.py:

    url(r'^logout/$', 'django.contrib.auth.views.logout',  {'next_page': '/'}, name='iamapps.logout'),
于 2012-12-25T19:45:48.313 回答
1

我的怀疑是原始注销视图返回一个清除 cookie 或类似内容的响应,而您正在丢弃该响应。您可以尝试像这样简单地将其响应返回给用户吗?

def my_logout(request):
    # something...
    return logout(request)
于 2012-12-25T23:49:12.893 回答
1

经过验证的答案适用于上述版本,但它不再适用于 django 2.2 版本。因此,为了在注销后成功重定向,您必须定义属性。

from django.contrib import admin
from django.urls import path, include
from dark_bot import views
from django.contrib.auth import views as v
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name="index"),
    path('contact/', views.contact, name="contact"),
    path('search/', include('search.urls')),
    path('user/', include('accounts.urls')),
    path('dashboard/', include('dashboard.urls')),
    path('accounts/login/', v.LoginView.as_view(), name="login"),
    path('accounts/logout/',v.LogoutView.as_view(next_page='/'),name="logout")
    # path('dashboard/', include('dashboard.urls')),
]

这就是你可以看到我将 next_page 属性传递给类 LogoutView 的方式,它将告诉在成功注销后重定向或去哪里。希望这可以帮助某人。快乐编码!

于 2019-07-29T07:53:13.817 回答