清理函数导致.is_valid()方法在表单django 1.9.8中使用时返回false

时间:2016-07-28 01:10:33

标签: django validation django-forms python-3.5 django-login

在我正在研究的django项目中,我编写了一个函数来验证登录表单中的数据。现在每当我在登录表单的一个实例上运行is_valid()方法时,它每次都返回false。我一直试图找出导致这个问题的原因。

forms.py

 from django import forms
 from django.contrib.auth import authenticate, password_validation
 from django.contrib.auth.forms import AuthenticationForm
 from django.contrib.auth.models import User, Group
 from .functions import *
 from .models import *

 class login_form(forms.Form):
     username = forms.CharField(max_length=64, label='Username', widget=forms.TextInput(attrs={'placeholder': 'username...', 'class':'login-field'}))
     password = forms.CharField(max_length=24, label='Password', widget=forms.PasswordInput(attrs={'placeholder': 'password...', 'class':'login-field'}))

     def clean(self, *args, **kwargs):
         username = self.cleaned_data.get('username', None)
         password = self.cleaned_data.get('password', None)
         user_obj = None
         self._errors['username'] = None  #clears default username error
         self._errors['password'] = None  #clears default password error

         if username is not None:
             try:
                 user_obj = User.objects.get(username=username) 

                 if password_validation.validate_password(password, user_obj) is None:
                     self._errors['password'] = 'Password is incorrect. Please try again.'

             except User.DoesNotExist:
                 self._errors['username'] = 'User does not exist. Please use valid credentials.'

         else:
             self._errors['username'] = 'Please type a valid username.'


         return super(login_form, self).clean(*args, **kwargs)

views.py

from django.shortcuts import render, redirect
from django.http import HttpRequest, JsonResponse, HttpResponse
from django.template import RequestContext
from django.conf.urls import patterns
from django.contrib import admin
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User, Group
from datetime import datetime
from .models import *
from .forms import *
from .functions import *
from os import *
import shutil
import json


 def home(request):
     if request.method == 'POST':
        form = login_form(request.POST)

        if form.is_valid():
            username = form.data.get('username')
            password = form.data.get('password')
            authenticate_usr_obj = authenticate(username=username, password=password)
            if authenticate_usr_obj is not None:
                login(request, authenticate_usr_obj)
                return redirect(dashboard)

     else:
         form = login_form()


     try:
        logout_successful = request.session.get('logout_complete', False)
        request.session['logout_complete'] = False

     except:
         logout_successsful = False

     context = {
        'body_class': 'login',
        'login': form,
        'logout_successful': logout_successful
     }

     return render(request, 'development/index.html', context)

2 个答案:

答案 0 :(得分:0)

通过阅读Forms API文档,我可以看到,在您的示例中,在尝试将数据排成行之前,您没有清理数据:

username = self.cleaned_data.get('username', None)
password = self.cleaned_data.get('password', None)

尝试首先使用clean()来验证数据,如下所示:

cleaned_data = super(login_form, self).clean()

然后你可以试着像这样:

username = cleaned_data.get('username', None)
password = cleaned_data.get('password', None)

您可以找到更多here

版本2:

好的,首先我在Django docs中找到关于django.contrib.auth.password_validation.validate_password()的内容:

  

Integrating validation

     

validate_password(密码,用户=无,密码_验证器=无)

     

验证密码。 如果所有验证程序都发现密码有效,则返回 。如果一个或多个验证器拒绝密码,则引发ValidationError,其中包含验证器的所有错误消息。

     

用户对象是可选的:如果未提供,则某些验证器可能无法执行任何验证并接受任何密码。

所以这一行:

if password_validation.validate_password(password, user_obj) is None:

应该是:

if password_validation.validate_password(password, user_obj) is not None:

其次:

  

Form.errors

>>>> f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}`
     

在此词典中,键是字段名称,值是表示错误消息的Unicode字符串列表。错误消息存储在列表中,因为字段可能有多个错误消息。

基于此,我会更改您定义自定义消息的行,看起来更像这样:

self.errors['password'] = [u'Password is incorrect. Please try again.']

最后要记住的是,clean方法必须返回cleaning_data。

forms.py代码的最终版本可能如下所示:

def clean(self):
    super(login_form,self).clean()
    username = self.cleaned_data.get('username', None)
    password = self.cleaned_data.get('password', None)

    if username is not None:
        try:
            user_obj = User.objects.get(username=username) 
            if password_validation.validate_password(password, user_obj) is not None:
                self.errors['password'] = [u'Password is incorrect. Please try again.']
        except User.DoesNotExist:
            self.errors['username'] = [u'User does not exist. Please use valid credentials.']
    else:
        self.errors['username'] = [u'Please type a valid username.']
    return self.cleaned_data

希望这次有所帮助。

答案 1 :(得分:0)

测试了上面的代码,由于表单self._errors

,我遇到了错误
`Nonetype` object is not iterable

这是我的建议

<强> forms.py

from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError


class login_form(forms.Form):
    username = forms.CharField(
        max_length=64, label='Username',
        widget=forms.TextInput(
            attrs={'placeholder': 'username...', 'class': 'login-field'}))
    password = forms.CharField(
        max_length=24, label='Password',
        widget=forms.PasswordInput(
            attrs={'placeholder': 'password...', 'class': 'login-field'}))

def clean_username(self):
    data = self.cleaned_data.get('username', None)
    if not data:
        raise ValidationError('Please type a valid username.',
                              code='invalid')
    return data

def clean(self, *args, **kwargs):
    username = self.cleaned_data.get('username')
    password = self.cleaned_data.get('password')
    try:
        user_obj = User.objects.get(username=username)
        if not user_obj.check_password(password):
            raise ValidationError(
                    'Password is incorrect. Please try again',
                    code='incorrect')

    except User.DoesNotExist:
        raise ValidationError(
            'User does not exist. Please use valid credentials.',
            code='invalid')
    return super(login_form, self).clean(*args, **kwargs)

<强> views.py

from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth import logout

from .forms import *


def home(request):
    logout_successful = True
    if request.method == 'POST':
        form = login_form(request.POST)
        # print form.errors

        if form.is_valid():
            username = form.data.get('username')
            password = form.data.get('password')
            authenticate_usr_obj = authenticate(
                username=username, password=password)
            if authenticate_usr_obj:
                login(request, authenticate_usr_obj)
                # print 'ok'
    else:
        form = login_form()
    logout_successful = request.user.is_authenticated()
    return render(request, 'base.html', {
        'body_class': 'login',
        'login': form,
        'logout_successful': logout_successful
    })


def logout_view(request):
    logout(request)

我还是初学者,所以请随意发表评论