在我正在研究的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)
答案 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
好的,首先我在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)
我还是初学者,所以请随意发表评论