clean 函数导致 .is_valid() 方法在表单 django 1.9.8 中使用时为 return false
clean function causing .is_valid() method to return false when used in form django 1.9.8
在我正在处理的 django 项目中,我编写了一个函数来验证来自登录表单的数据。现在,每当我 运行 登录表单实例上的 is_valid()
方法时,它每次都会 returns 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)
通过阅读 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 文档中发现了关于 django.contrib.auth.password_validation.validate_password():
Integrating validation
validate_password(password, user=None, password_validators=None)
Validates a password. If all validators find the password valid, returns None. If one or more validators reject the password, raises a ValidationError with all the error messages from the validators.
The user object is optional: if it’s not provided, some validators may not be able to perform any validation and will accept any password.
所以行:
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.']}`
In this dictionary, the keys are the field names, and the values are lists of Unicode strings representing the error messages. The error messages are stored in lists because a field can have multiple error messages.
因此,基于此,我会更改您定义自定义消息的行,使其看起来更像这样:
self.errors['password'] = [u'Password is incorrect. Please try again.']
最后一件事要记住,clean 方法必须 return cleaned_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
希望这次能有所帮助。
测试了你上面的代码,我遇到了表单错误 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)
我还是个初学者,所以请随意发表评论
在我正在处理的 django 项目中,我编写了一个函数来验证来自登录表单的数据。现在,每当我 运行 登录表单实例上的 is_valid()
方法时,它每次都会 returns 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)
通过阅读 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 文档中发现了关于 django.contrib.auth.password_validation.validate_password():
Integrating validation
validate_password(password, user=None, password_validators=None)
Validates a password. If all validators find the password valid, returns None. If one or more validators reject the password, raises a ValidationError with all the error messages from the validators.
The user object is optional: if it’s not provided, some validators may not be able to perform any validation and will accept any password.
所以行:
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.']}`
In this dictionary, the keys are the field names, and the values are lists of Unicode strings representing the error messages. The error messages are stored in lists because a field can have multiple error messages.
因此,基于此,我会更改您定义自定义消息的行,使其看起来更像这样:
self.errors['password'] = [u'Password is incorrect. Please try again.']
最后一件事要记住,clean 方法必须 return cleaned_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
希望这次能有所帮助。
测试了你上面的代码,我遇到了表单错误 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)
我还是个初学者,所以请随意发表评论