Django LoginFormMiddleware打破了基于类的视图 [英] Django LoginFormMiddleware breaks with class based views
问题描述
根据一些其他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屋!