Django表单form.is_valid()始终为false

17

我正在编写一个登录功能。当我手动编写表单时,它能够正常工作。

下面的代码有效:

views.py

def login_view(request):
    if request.method == 'GET':
        return render(request, 'app/login.htm')
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username, password=password)
        if user is None:
            return HttpResponseRedirect(reverse('error'))
        if not user.is_active:
            return HttpResponseRedirect(reverse('error'))

        # Correct password, and the user is marked "active"
        auth.login(request, user)
        # Redirect to a success page.
        return HttpResponseRedirect(reverse('home'))

模板:

<form method="post" action="{% url 'login'  %}">
    {% csrf_token %}
    <p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="30" /></p>
    <p><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></p>

    <input type="submit" value="Log in" />
    <input type="hidden" name="next" value="" />
</form>

太好了!但现在我想使用Django的表单来做同样的事情。

因为我总是得到is_valid() == False,所以下面的代码不起作用。

views.py:

def login_view(request):
    if request.method == 'POST':
        form = AuthenticationForm(request.POST)
        print form.is_valid(), form.errors, type(form.errors)
        if form.is_valid():
            ## some code....
            return HttpResponseRedirect(reverse('home'))
        else:
            return HttpResponseRedirect(reverse('error'))
    else:
        form = AuthenticationForm()
    return render(request, 'app/login.htm', {'form':form})

模板:

<form action="{% url 'login' %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />

在stackoverflow上有很多人抱怨他们得到的 is_valid 总是 false。我已经阅读了所有这些帖子,据我所知,我没有犯任何一个错误。我发现了一个新的错误 :-)

编辑:我在代码中添加了一个打印。当打开登录视图并提交时,输出为

[27/Dec/2013 14:01:35] "GET /app/login/ HTTP/1.1" 200 910
False  <class 'django.forms.util.ErrorDict'>
[27/Dec/2013 14:01:38] "POST /app/login/ HTTP/1.1" 200 910

所以 is_valid() 是 False,但 form.errors 是空的。


1
为什么在出现错误的情况下要进行重定向?如果不这样做,表单将会重新渲染并显示错误信息,您就可以清楚地知道表单无效的原因。请完全删除第一个else子句。 - Daniel Roseman
我按照你说的删除了第一个 else 子句,提交后,表单只是被重新渲染并清空了。 - user1950164
3个回答

19

事实证明,Maxime是对的(抱歉) - 您确实需要data参数:

form = AuthenticationForm(data=request.POST)

不过,原因在于 AuthenticationForm 覆盖了 __init__ 的签名来期望 request 作为第一个位置参数。如果你明确地提供了 data 作为关键字参数,它将起作用。

(不过,在错误情况下仍然应该省略重定向的 else 子句:在这种情况下,让表单重新呈现自身并显示错误是最佳实践。)


没错,那就解决了。你能带我走一遍你得出这个结论的思考过程吗?你知道,有关教人如何钓鱼的那种东西... - user1950164
1
我查看了源代码。虽然如果我此刻在一台带有Python shell的电脑上,我会直接导入该类并执行help(AuthenticationForm),这将给我提供签名信息。 - Daniel Roseman
2
你知道吗,现在我经常去读源代码... :-) 已经快3年了。天哪。 - user1950164

12

请查看 form.errors,它可以帮助您找出原因。


是的,在其他类似的问题中,人们也这样说。我尝试了一下,但form.errors为空。它是django.forms.util.ErrorDict类型的对象,但里面什么都没有。 - user1950164

0

如果出现这种情况,你没有其他选择(我试图使用bootstrap模态框,但它根本不起作用),我必须这样做,否则即使表单没有问题,模态框也会一直触发(并且is_valid默认始终为False

我需要的是:

  • 点击按钮时显示模态框
  • 如果有错误,在同一页上显示模态框和错误信息。

在模态框模板中:

{% if not brand_form.is_valid and brand_form.errors %}
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
        <script type="text/javascript">
             $(window).on('load', (function() {
                $('#brandAddModal').modal('show');
             }));
        </script>
                    
          {{ brand_form.non_field_errors }}
{% endif %}

在视图中:

def add_brand_form(request):
    form = BrandForm()
    if request.method == 'POST':
        form = BrandForm(data=request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/home')
        else:
            return render(request, template_name='home.html', context={'brand_form':form})
        
    return render(request, template_name='modal_add_brand.html', context={'brand_form':form})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接