Django 自定义用户身份验证无法正常工作
Django custom user authentication is not working properly
我正在使用自定义用户身份验证模型,该模型使用电子邮件地址作为用户名并创建用户,但即使密码 1 与密码 2 不同,注册也会成功完成。 我无法调试问题。
这里是models.py文件:
class UserManager(auth_models.BaseUserManager):
def create_user(self, email, first_name, last_name, password):
"""
Creates and saves a user with given email,
first name, last name and password.
"""
if not email:
raise ValueError("users must have an email address")
user = self.model(
email=UserManager.normalize_email(email),
first_name=first_name,
last_name=last_name,
)
user.set_password(password)
user.save(self._db)
return user
def create_superuser(self, email, first_name, last_name, password):
"""
Creates and saves a super_user with given email,
first name, last name and password.
"""
if not email:
raise ValueError("users must have an email address")
user = self.model(
email=UserManager.normalize_email(email),
first_name=first_name,
last_name=last_name,
)
user.is_admin = True
user.set_password(password)
user.save(self._db)
return user
class User(auth_models.AbstractBaseUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
joined_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', ]
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.first_name
def __str__(self):
return self.get_full_name() + ", email= " + self.email
@property
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
class Meta:
verbose_name_plural = "users"
admin.py
class UserCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(label='password', widget=forms.PasswordInput)
password2 = forms.CharField(label='confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
def clean_password(self):
"""
check that the two password entries match
"""
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match")
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""
A form for updating users. includes all the fields
on the user, but replaces the password field with
the admin's password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'password', 'is_active', 'is_admin')
def clean_password(self):
"""
Regardless of what the user provides, return the initial value.
This is done here, rather than on the field, because the field
does not have access to the initial value.
"""
return self.initial["password"]
views.py
def register(request):
args = {}
args.update(csrf(request))
if request.method == 'POST':
form = UserCreationForm(request.POST)
args['form'] = form
if form.is_valid():
form.save()
return HttpResponseRedirect('/home/')
else:
args['form'] = UserCreationForm()
return render_to_response('authentication/signup.html', args, context_instance=RequestContext(request))
尝试将 clean_password()
函数中存在的密码比较逻辑移动到 UserCreationForm
中的 clean()
函数。
clean_fieldname()
函数应该在字段 fieldname
而不是任何其他字段上运行。
此外,当字段验证相互依赖时,放置验证逻辑的最佳位置是在 clean()
方法中。
We are performing validation on more than one field at a time, so the
form’s clean()
method is a good spot to do this.
By the time the form’s clean()
method is called, all the individual
field clean methods will have been run (the previous two sections), so
self.cleaned_data
will be populated with any data that has survived so
far. So you also need to remember to allow for the fact that the
fields you are wanting to validate might not have survived the initial
individual field checks.
代码:
class UserCreationForm(forms.ModelForm):
...
def clean(self):
cleaned_data = super(UserCreationForm, self).clean()
password1 = cleaned_data.get("password1")
password2 = cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match")
return cleaned_data
问题是,您没有 'password' 字段,
您需要将方法名称更改为 clean_password1 或 clean_password2.
the method you created clean_password, will never be called
because there is no field called password
def clean_password1(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match"")
return password1
我正在使用自定义用户身份验证模型,该模型使用电子邮件地址作为用户名并创建用户,但即使密码 1 与密码 2 不同,注册也会成功完成。 我无法调试问题。
这里是models.py文件:
class UserManager(auth_models.BaseUserManager):
def create_user(self, email, first_name, last_name, password):
"""
Creates and saves a user with given email,
first name, last name and password.
"""
if not email:
raise ValueError("users must have an email address")
user = self.model(
email=UserManager.normalize_email(email),
first_name=first_name,
last_name=last_name,
)
user.set_password(password)
user.save(self._db)
return user
def create_superuser(self, email, first_name, last_name, password):
"""
Creates and saves a super_user with given email,
first name, last name and password.
"""
if not email:
raise ValueError("users must have an email address")
user = self.model(
email=UserManager.normalize_email(email),
first_name=first_name,
last_name=last_name,
)
user.is_admin = True
user.set_password(password)
user.save(self._db)
return user
class User(auth_models.AbstractBaseUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
joined_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', ]
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.first_name
def __str__(self):
return self.get_full_name() + ", email= " + self.email
@property
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
class Meta:
verbose_name_plural = "users"
admin.py
class UserCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(label='password', widget=forms.PasswordInput)
password2 = forms.CharField(label='confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
def clean_password(self):
"""
check that the two password entries match
"""
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match")
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""
A form for updating users. includes all the fields
on the user, but replaces the password field with
the admin's password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'password', 'is_active', 'is_admin')
def clean_password(self):
"""
Regardless of what the user provides, return the initial value.
This is done here, rather than on the field, because the field
does not have access to the initial value.
"""
return self.initial["password"]
views.py
def register(request):
args = {}
args.update(csrf(request))
if request.method == 'POST':
form = UserCreationForm(request.POST)
args['form'] = form
if form.is_valid():
form.save()
return HttpResponseRedirect('/home/')
else:
args['form'] = UserCreationForm()
return render_to_response('authentication/signup.html', args, context_instance=RequestContext(request))
尝试将 clean_password()
函数中存在的密码比较逻辑移动到 UserCreationForm
中的 clean()
函数。
clean_fieldname()
函数应该在字段 fieldname
而不是任何其他字段上运行。
此外,当字段验证相互依赖时,放置验证逻辑的最佳位置是在 clean()
方法中。
We are performing validation on more than one field at a time, so the form’s
clean()
method is a good spot to do this.By the time the form’s
clean()
method is called, all the individual field clean methods will have been run (the previous two sections), soself.cleaned_data
will be populated with any data that has survived so far. So you also need to remember to allow for the fact that the fields you are wanting to validate might not have survived the initial individual field checks.
代码:
class UserCreationForm(forms.ModelForm):
...
def clean(self):
cleaned_data = super(UserCreationForm, self).clean()
password1 = cleaned_data.get("password1")
password2 = cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match")
return cleaned_data
问题是,您没有 'password' 字段, 您需要将方法名称更改为 clean_password1 或 clean_password2.
the method you created clean_password, will never be called because there is no field called password
def clean_password1(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("passwords don't match"")
return password1