简体   繁体   中英

Django form.is_valid() always false

I'm coding a login. When I programmed the form by hand I got it working.

The code below works:

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'))

template:

<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>

Great! But now I want to do the same thing using Django's forms.

The code below is not working because I get is_valid() == False, always.

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})

template:

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

There are a bunch of people on stackoverflow complaining that they get is_valid always false. I have read all those posts, and as far as I can tell I'm not making any of those mistakes. I found a new mistake to make :-)

EDIT: I added a print in the code. The output when opening the login view and submitting is

[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

and so is_valid() is False, but form.errors is empty.

It turns out that Maxime was right after all (sorry) - you do need the data parameter:

form = AuthenticationForm(data=request.POST)

The reason for that, though, is that AuthenticationForm overwrites the signature of __init__ to expect the request as the first positional parameter. If you explicitly supply data as a kwarg, it will work.

(You should still leave out the else clause that redirects away on error, though: it's best practice to let the form re-render itself with errors in that case.)

查看form.errors这将帮助您找出原因。

If situation arises, that you don't have an option (I was trying to work with bootstrap modals and it was just not working), I had to do this, or else the modal would always trigger even if the form had not issues ( and the is_valid is always False by default )

What I needed:

  • Show modal when I click a button
  • if errors, show on the same page, the modal, with the error.

In the modal template:

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

In the view:

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})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM