Django自定义登录-表单有效但无错误

Django自定义登录-表单有效但无错误,django,authentication,login,Django,Authentication,Login,我目前正试图找出如何自定义基本Django用户登录功能,以添加例如简单验证码 我从django.contrib.auth.forms 第一个看起来很好,但如果我尝试登录,我根本无法登录 我已经调试了代码,目前只得到: 响应=包装的回调(请求,*回调参数, **callback_-kwargs)TypeError:init()接受1个位置参数,但给出了2个 accounts/views.py: ... ... django.contrib.auth.forms子类化(复制)到accounts/

我目前正试图找出如何自定义基本Django用户登录功能,以添加例如简单验证码

我从
django.contrib.auth.forms
第一个看起来很好,但如果我尝试登录,我根本无法登录

我已经调试了代码,目前只得到:

响应=包装的回调(请求,*回调参数, **callback_-kwargs)TypeError:init()接受1个位置参数,但给出了2个

accounts/views.py

...
...
django.contrib.auth.forms子类化(复制)到accounts/forms.py的登录表单:

...
url.py

...
...

这里有一些问题

主要的一点是,您已经重写了类init签名,因此第一个位置参数是
request
,但是您在该位置传递了POST数据;因此,表单永远不会受到约束,也永远不会有效

其次,如果表单无效,您会出于某种原因重新实例化它,因此模板永远不会显示任何验证错误。除非你有很好的理由,否则你应该坚持文档中显示的标准表单处理结构

把这些放在一起:

def login (request):
    if request.method == 'POST':
        form = LoginForm(request, data=request.POST)
        if form.is_valid():
            form.save()
            messages.add_message(request, messages.INFO, "You are now logged-In, welcome")
            return redirect(reverse('post_list'))
    else:
        form = LoginForm(request)

        args = {'form': form}
    return render(request, 'registration/login.html', args)

注意,您不需要第二个
else
块;这里的单个函数与第一个
if
对齐,最后的
返回值在两种情况下都被命中。

正如Daniel所说,您更新了表单的init方法。所以您必须将请求作为第一个参数传递

第二个是当您验证用户信息时,您必须使用身份验证后端对用户进行身份验证。但是您保存了表单数据

如果您只想更改身份验证表单,您可以像这样使用登录视图

见下文: url.py

如果您使用django2和更高版本,您可以这样更改它。首先,在这个类中创建一个基于类的视图,该视图由django.contrib.auth.views.LoginView扩展而来,并将form_类设置为如下所示

from django.conrtib.auth.views import LoginView
...
class NewLoginView(LoginView):
    form_class = LoginForm
然后您必须更新URL,如下所示:

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

您必须从django.contrib.auth.forms.AuthenticationForm扩展表单,或者必须实现此表单类所需的所有功能。

我终于找到了一个解决方案,puh:D

views.py:

...
from django.contrib.auth import update_session_auth_hash, authenticate, login as customlogin
...

def login(request):
    if request.method == 'POST':
        form = LoginForm(request.POST, request.POST)
        if form.is_valid():
            username = request.POST['username']
            password = request.POST['password']
            user = authenticate(request, username=username, password=password)
            if user is not None:
                customlogin(request, user)
                # Redirect to a success page.
                return redirect(reverse('post_list'))
        return render(request, 'registration/login.html', {'form': form})
    else:
        return render(request, 'registration/login.html', {'form': LoginForm()})
只需扩展表单(感谢vorujack)

URL.py:

url(r'^accounts/login/$', views_accounts.login, name='login'),
真正愚蠢的部分是登录函数“form=LoginForm(request.POST,request.POST)” 你真的需要把它传递给密码和用户,除此之外还有第二个请求。发布验证码表单。。。好的。不管怎样,现在它起作用了


感谢所有人的帮助,我真的很感激这个社区

当我用沃鲁杰克的方法犯了错误,最后我找到了解决办法

在url中

from django.contrib.auth import views as auth_views

path('login/',auth_views.LoginView.as_view(form_class=forms.new_login_form,
    template_name='login.html'), name='login'),
以形式

from django.contrib.auth.forms import AuthenticationForm
class new_login_form(AuthenticationForm):
    captcha = CaptchaField(label='验证码', error_messages={"invalid": "验证码错误"})

    class Meta:
        model = User
        fields = ('username', 'password',)

login()得到了一个意外的关键字参数“authentication\u form”,它是Django的一个版本。除此之外,这个解决方案很不公平,因为我无法以这种方式添加captcha字段。要使用django simple captcha中的验证码,您需要将其直接实现到表单中,这就是为什么我要将其子类化;)我的解决方案基于django2.x。我更新了django2.1Hey的解决方案,我刚刚尝试了您的解决方案,但得到的结果是:“LoginForm”对象没有“save”属性。我想我甚至不需要它。如果我删除了它,我就不会登录并被重定向到帖子列表。你没有登录。您只能检查用户信息并重定向到特定用户。检查您的视图中是否存在
request.user
并且是否是经过身份验证的用户。@沃鲁杰克,我的视图现在看起来像丹尼尔·罗斯曼的帖子。您可以发布您的解决方案吗?>>“LoginForm”对象没有属性“save”,我更新了此答案,但您查看了旧答案,因为Daniel不接受它
form=LoginForm(request.post,request.post)
。什么是LoginForm?你为什么要两次通过这个职位?最好的答案是:)