我想在我的网站上随处放置一个登录表单,在听完几个SO答案之后我决定编写我自己的中间件:
class LoginFormMiddleware(object):
'''
Put a login form in everypage of the website
'''
def process_request(self, request):
# if the top login form has been posted
if request.method == 'POST':
if 'logout_submit' in request.POST:
# log the user out
from django.contrib.auth import logout
logout(request)
form = LoginForm()
elif 'login_submit' in request.POST:
# validate the form
form = LoginForm(data=request.POST)
if form.is_valid():
# log the user in
from django.contrib.auth import login
login(request, form.get_user())
else:
form = LoginForm(request)
else:
form = LoginForm(request)
# attach the form to the request so it can be accessed
# within the templates
request.login_form = form
在我的settings.py中,我有:
import django.conf.global_settings as DEFAULT_SETTINGS
...
MIDDLEWARE_CLASSES = DEFAULT_SETTINGS.MIDDLEWARE_CLASSES + (
'base.mymiddleware.LoginFormMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
'django.core.context_processors.request',
)
从base.html开始的base.html中的表单如下所示:
{% if user.is_authenticated %}
<div class="login_box">
<form action="/myapp/logout/" method="post">{% csrf_token %}
<div class="col2"><a>{{ user.username }}</a></div>
<div class="col3"><input type="submit" value="Logout" name="logout_submit"/></div>
</form>
</div>
{% else %}
<form action="." method="post">
{% csrf_token %}
<div class="login_box">
<div class="error_box">
{% if request.login_form.errors %}
Incorrect User/Password
{% endif %}
</div>
<div class="col00"> <h4>{{ request.login_form.username.label_tag }}</h3></div>
<div class="col11">{{ request.login_form.username }}</div>
<div class="col22"><h4>{{ request.login_form.password.label_tag }}</h3></div>
<div class="col33">{{ request.login_form.password }}</div>
<div class="col44"><input type="submit" value="Login" name="login_submit"/></div>
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
</div>
</form>
{% endif %}
登录正常工作,但在执行之后,每次我发出GET请求时,user.is_authenticated似乎都返回false,因为我看到的是一个空的LoginForm而不是注销表单。
我不知道问题是否在我的中间件中(当request.method!='POST'它返回form = LoginForm(请求))或者我在设置中缺少的东西,或者可能使用中间件这是不是一个好主意...
答案 0 :(得分:1)
我无法相信你已经看到任何提倡将这种逻辑放在中间件中的SO答案。 (如果有,请发布链接,以便我可以对它们进行投票。)
这真的,真的,真的不是做这种事情的地方。编写特定视图并将登录表单的操作参数设置为该视图。
但是,我怀疑您的根本问题是您没有使用RequestContext来呈现其他视图,因此用户对象不会传递给模板。
答案 1 :(得分:0)
您的实施没有多大意义。具有action属性的登录表单是“。”错了,会导致冲突。
您应该登录查看,而不是登录中间件。登录表单的action属性应该是登录视图的反向URL。
在您的登录表单中,您应指定下一个隐藏的输入,例如:
<input name="next" type="hidden" value="{{ request.POST.next|default:request.path }}" />
然后,它可以在您的基本模板中或网站中的任何位置。
这对退出也有效。