2012-03-05 33 views
0

我想提出一个登录表单无处不在我的网站,之后跟随几个SO答案,我决定写我自己的中间件是这样的:在我的settings.pyDjango的 - 中间件问题

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 

,我有:

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文件将被来自世界各地的accesed,看起来是这样的:

{% 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 %} 

登录工作normall y但是,做完之后,每次我发出GET请求时,user.is_authenticated似乎都会返回false,因为我看到的是一个空的LoginForm,而不是注销表单。如果request.method!='POST'返回form = LoginForm(request)),或者我在我的设置中缺少某些东西,或者可能使用了中间件来实现这个功能不是一个好主意......

+0

请添加您的相关视图。我个人不明白在这种情况下使用中间件的目的,Django提供了一个体面的登录和退出模块。 – 2012-03-05 11:18:50

+0

我的看法不做太多的原因,所有的工作都是在中间件中,实际上,我在里面使用django登录。 Login和Logout视图只有这一行:return HttpResponseRedirect(request.META.get('HTTP_REFERER'))。使用中间件的原因是因为我想在我的站点中的任何地方使用这种表单,而不是在HTML之外的版本 – juankysmith 2012-03-05 11:22:53

+0

如果您使用模板继承,Django的auth中间件已经将'user'对象添加到'dict', (你应该)_,你可以把表单放在你的base.html中,这样它会被加载到每一页 – 2012-03-05 11:28:50

回答

1

我不敢相信你已经看到任何SO的答案,提倡把这种逻辑在中间件。 (如果你有,发布链接,以便我可以downvote他们。)

这真的,真的,真的不是做这种事情的地方。编写特定的视图并将登录表单的操作参数设置为该视图。

但是,我怀疑你的根本问题是你没有使用RequestContext来渲染其他视图,所以用户对象不会传递给模板。

+0

http://stackoverflow.com/questions/2734055/putting-a-django-login-form-on-every-page – juankysmith 2012-03-05 11:34:40

+0

@juankysmith这就是为什么我们有'@ login_required'装饰器 – 2012-03-05 11:49:17

+0

对不起我的无知但我无法看到装饰者与在每个视图之后显示表单的事实之间的关系 – juankysmith 2012-03-05 12:08:48

0

你的实现没有多大意义。具有操作属性的登录表单是“。”是错误的,会导致冲突。

您应该有一个登录查看,而不是登录中间件。登录表单的action属性应该是您的登录视图的反向链接。

在你的登录表单,你应该例如指定下一个隐藏输入:

<input name="next" type="hidden" value="{{ request.POST.next|default:request.path }}" /> 

在此之后,它可以在你的基本模板,或在网站上的任何地方。

这也适用于注销。

+0

所以......我必须在每个视图的返回中传递表单吗? – juankysmith 2012-03-05 11:47:32

+0

你为什么要这么做?只需粘贴表单的HTML。这就是我们对betspire.com的看法,它很简单,也很理智。 – jpic 2012-03-05 12:47:13

+0

是的,我想要做的是像betspire的登录。它是否使用视图进行登录? – juankysmith 2012-03-05 13:36:55