django 2 自定义用户:属性错误(密码不正确 passing/hashing)
django 2 Custom User: Attribute Error (password not passing/hashing properly)
我已经为 django 2 实现了自定义用户设置。但是,我似乎无法找出我尝试注册时发生的此错误的来源。
AttributeError at /register/
'AnonymousUser' object has no attribute '_meta'
当我收到此错误时,密码在没有散列的情况下传递并且没有保存到数据库中,而其他值通过正常。
models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import ugettext_lazy as _
class MyUserManager(BaseUserManager):
def _create_user(self, email, password):
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email,)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
USERNAME_FIELD = 'email'
objects = MyUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib import messages
from . forms import RegisterForm
def home(request):
return render(request, 'authenticate/home.html', {})
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ('Welcome Back'))
return redirect('home')
else:
messages.success(request, ('No account matches those credentials. Please try again.'))
return redirect('login')
else:
return render(request, 'authenticate/login.html', {})
def logout_user(request):
logout(request)
messages.success(request, ('Successfully logged out'))
return redirect('home')
def register_user(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data['email']
password = form.cleaned_data['password1']
user = authenticate(email=email, password=password)
login(request, user)
messages.success(request, ('Welcome to Keto2Go!'))
return redirect('home')
else:
form = RegisterForm()
context = {'form': form}
return render(request, 'authenticate/register.html', context)
def edit_profile(request):
if request.method == 'POST':
form = UserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
messages.success(request, ('You have updated your profile'))
return redirect('home')
else:
form = UserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'authenticate/edit_profile.html', context)
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
messages.success(request, ('Your password has been updated.'))
return redirect('home')
else:
form = PasswordChangeForm(user=request.user)
context = {'form': form}
return render(request, 'authenticate/change_password.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from . models import User
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_password2(self):
# Check that the two password entries match
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'password')
def clean_password(self):
return self.initial["password"]
在注册时,您正在尝试使用关键字参数 email
进行身份验证,但身份验证没有任何关键字 email
,它需要 username
和 password
(除非您在自定义后端覆盖它)。所以像这样尝试(就像你的 login_user
视图):
authenticate(request, username=email, password=password)
有关详细信息,请参阅 documentation。
另外,您的密码不会以哈希格式保存,因为您是使用 save
方法直接将其保存到数据库中,而没有使用 set_password
。您需要更新 Registration
形式的保存方法(就像您的 UserAdminCreationForm
)
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
我已经为 django 2 实现了自定义用户设置。但是,我似乎无法找出我尝试注册时发生的此错误的来源。
AttributeError at /register/
'AnonymousUser' object has no attribute '_meta'
当我收到此错误时,密码在没有散列的情况下传递并且没有保存到数据库中,而其他值通过正常。
models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import ugettext_lazy as _
class MyUserManager(BaseUserManager):
def _create_user(self, email, password):
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email,)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
USERNAME_FIELD = 'email'
objects = MyUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib import messages
from . forms import RegisterForm
def home(request):
return render(request, 'authenticate/home.html', {})
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ('Welcome Back'))
return redirect('home')
else:
messages.success(request, ('No account matches those credentials. Please try again.'))
return redirect('login')
else:
return render(request, 'authenticate/login.html', {})
def logout_user(request):
logout(request)
messages.success(request, ('Successfully logged out'))
return redirect('home')
def register_user(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data['email']
password = form.cleaned_data['password1']
user = authenticate(email=email, password=password)
login(request, user)
messages.success(request, ('Welcome to Keto2Go!'))
return redirect('home')
else:
form = RegisterForm()
context = {'form': form}
return render(request, 'authenticate/register.html', context)
def edit_profile(request):
if request.method == 'POST':
form = UserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
messages.success(request, ('You have updated your profile'))
return redirect('home')
else:
form = UserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'authenticate/edit_profile.html', context)
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
messages.success(request, ('Your password has been updated.'))
return redirect('home')
else:
form = PasswordChangeForm(user=request.user)
context = {'form': form}
return render(request, 'authenticate/change_password.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from . models import User
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_password2(self):
# Check that the two password entries match
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'password')
def clean_password(self):
return self.initial["password"]
在注册时,您正在尝试使用关键字参数 email
进行身份验证,但身份验证没有任何关键字 email
,它需要 username
和 password
(除非您在自定义后端覆盖它)。所以像这样尝试(就像你的 login_user
视图):
authenticate(request, username=email, password=password)
有关详细信息,请参阅 documentation。
另外,您的密码不会以哈希格式保存,因为您是使用 save
方法直接将其保存到数据库中,而没有使用 set_password
。您需要更新 Registration
形式的保存方法(就像您的 UserAdminCreationForm
)
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user