Django LoginFormMiddleware打破了基于类的视图 [英] Django LoginFormMiddleware breaks with class based views

查看:119
本文介绍了Django LoginFormMiddleware打破了基于类的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据一些其他SO答案,我正在使用中间件在我项目的每个页面上显示登录表单,以便用户可以就地登录。我知道对此有些皱眉,但这确实可以带来更好的用户体验。理想情况下,它是异步的,但我还没到那儿。

As per a few other SO answers, I'm using middleware to show a login form on every page of my project, such that a user can login in-place. I am aware some frown upon this, but it really does make for a much better user experience. Ideally it'd be asynchronous, but I haven't gotten there.

无论如何,middleware.py:

Anyway, middleware.py:

from MyProj.forms import MyProjTopLoginForm
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

#Notes: https://stackoverflow.com/questions/2734055/putting-a-django-login-form-on-every-page
class LoginFormMiddleware(object):

    def process_request(self, request):

        # if the top login form has been posted
        if request.method == 'POST' and 'top_login_form-username' in request.POST:

            # validate the form
            form = MyProjTopLoginForm(prefix="top_login_form", data=request.POST)
            if form.is_valid():

                # log the user in
                from django.contrib.auth import login
                login(request, form.get_user())

                # if this is the logout page, then redirect to /
                # so we don't get logged out just after logging in
                if reverse('logout') in request.get_full_path():
                    return HttpResponseRedirect('/')
                #return HttpResponseRedirect('/')

        else:
            form = MyProjTopLoginForm(request, prefix="top_login_form")

        # attach the form to the request so it can be accessed within the templates
        request.top_login_form = form

class LogoutFormMiddleware(object):
    def process_request(self, request):
        if request.method == 'POST' and request.POST.has_key('logout-button') and request.POST['logout-button'] == 'logout':
            from django.contrib.auth import logout
            logout(request)
            request.method = 'GET'

和视图.py:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.db.models import Count
from django.core.urlresolvers import reverse

from django.views.generic import TemplateView

class Index(TemplateView):
    template_name = 'KReport2/index.djhtml'

'''
def index(request):
    return render(request, 'KReport2/index.djhtml')
'''

def logoutpage(request):
    from django.contrib.auth import logout
    logout(request)
    return redirect(index)

您会注意到我已评论旧的索引视图功能,并将其替换为基于类的视图。通常,我不会继承该类,而是在urls.py中传递template_name,但这并不重要。我的问题似乎是中间件损坏。在索引页面上填写UN / Pass,然后提交,中间件捕获表单并登录我,但是django继续返回空白的http响应。没有错误,也没有呈现的索引页。我只是不知道中断在哪里发生。

You'll note that I've commented the old index view function and replaced it with a class-based view. Normally I wouldn't subclass, but instead pass template_name in urls.py, but that's besides the point here. My problem seems to be that the middleware breaks. Filling in UN/Pass on the index page, then submitting, the middleware captures the form and logs me in, but then django goes on to return a blank http response. No error, but also no rendered index page. I've just got no idea where the break is happening.

推荐答案

在基于类的视图中,默认的 dispatch 方法尝试

In class based views, the default dispatch method attempts to delegate to a method corresponds to the HTTP method.

TemplateView 仅实现 get()方法,因此它仅适用于GET请求。当您使用 POST 请求登录时,调度方法将查找 TemplateView.post()方法。因为不存在,所以它返回HTTP错误405(不允许使用方法)。

The TemplateView only implements a get() method, so it only works for GET requests. When you log in with a POST request, the dispatch method looks for TemplateView.post() method. Because this does not exist, it returns an HTTP Error 405 (Method not allowed).

在中间件中,建议您在成功登录后重定向到相同的url。 。 发布/重定向/获取模式一般来说是个好建议。浏览器将遵循重定向,并通过GET请求获取 IndexView ,该请求将成功。

In your middleware, I suggest that you redirect to the same url after a successful login. This Post/Redirect/Get pattern is good advice in general. The browser will follow the redirect, and fetch the IndexView with a GET request, which will be successful.

if form.is_valid():
    # log the user in
    from django.contrib.auth import login
    login(request, form.get_user())

    # if this is the logout page, then redirect to /
    # so we don't get logged out just after logging in
    if reverse('logout') in request.get_full_path():
        return HttpResponseRedirect('/')
    # redirect to the same url after a successful POST request.
    return HttpResponseRedirect('')

最后,浏览器可能会显示空白页面,但是有更多信息可用于调试。 Django开发服务器将显示它返回405错误代码。使用浏览器的开发人员工具栏,该工具栏应显示错误代码 405不允许使用的方法 Allow:get,head 标头,告诉您该视图不允许发布请求。

Finally, the browser might display a blank page, but there's more information that can be useful for debugging. The Django dev server will show that it returned a 405 error code. Use the developer toolbars for your browser, which should show you the description of the error code 405 METHOD NOT ALLOWED, and the Allow:get, head header which tells you that the view does not allow post requests.

这篇关于Django LoginFormMiddleware打破了基于类的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆