Django自定义用户模型的注册与登录技术问题求助
嘿,我来帮你搞定这两个困扰你的问题,咱们一个个拆解:
问题1:使用UserCreationForm注册时验证失败
你遇到的「The Users could not be created because the data didn't validate.」错误,主要有三个原因,咱们一步步修复:
1. 移除自定义用户模型中重复的password字段
你的Users模型继承了AbstractBaseUser,这个父类已经自带了哈希后的password字段(CharField,max_length=128),你自己额外定义的password = models.CharField(max_length=100)会覆盖父类的字段,导致密码哈希逻辑混乱,直接破坏UserCreationForm的验证流程。
修改后的models.py用户模型:
class Users(AbstractBaseUser): user_id = models.AutoField(primary_key=True) user_email = models.EmailField(max_length=100, unique=True) # 删掉这行重复的password定义! registration_date = models.DateField(auto_now_add=True) last_login = models.DateField(auto_now_add=True) is_administrator = models.BooleanField(default=False) is_active = models.BooleanField(default=True) email_verified = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'user_email'
2. 简化UserCreationForm子类
UserCreationForm已经自动包含password1和password2字段,不需要手动在fields里指定,只需要关联你的自定义用户模型即可:
class RegistrationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = get_user_model() fields = ('user_email',) # 只需要指定用户名字段(你的是user_email)
3. 修复注册视图的is_valid调用错误
你原来的视图里写的是if form.is_valid:,少了括号!这是方法调用,必须加括号才能触发验证逻辑:
def register(request): if request.method == "POST": form = RegistrationForm(request.POST) if form.is_valid(): # 这里一定要加括号! form.save() # 建议加个重定向,比如跳转到登录页 return redirect('login') else: form = RegistrationForm() return render(request, 'web/page.html', {'form': form})
问题2:check_password始终返回False
这个问题的核心是密码没有被正确哈希存储,加上视图里的小细节问题:
1. 先解决用户模型的password字段问题(和问题1的第一步一致)
删掉自定义的password字段,让AbstractBaseUser的password字段正常工作,这样set_password方法才能正确哈希密码。
2. 修复自定义注册表单的硬编码密码错误
看你原来的自定义RegistrationForm的save方法,你写了user.set_password("password")——这是硬编码成了字符串"password",不管用户输入什么密码,存储的都是这个固定字符串的哈希值,当然验证失败!改成用户输入的密码:
def save(self, commit=True): user = super(RegistrationForm, self).save(commit=False) # 用用户输入的密码,而不是硬编码的字符串 user.set_password(self.cleaned_data["password"]) # 注意:registration_date和last_login已经设置了auto_now_add=True,不需要手动赋值 if commit: user.save() return user
3. 修复登录视图的参数匹配和错误处理
- 确保你从POST中获取的邮箱字段名和表单一致:你的LoginForm字段是
user_email,所以应该用form.cleaned_data.get('user_email')(直接用POST.get容易拿到未验证的数据) - 增加用户不存在的异常捕获,避免崩溃
- 验证成功后重定向到主页,而不是返回登录页
修改后的登录视图:
def login_user(request): if request.method == "POST": form = LoginForm(request.POST) if form.is_valid(): user_email = form.cleaned_data.get('user_email') password = form.cleaned_data.get('password') UserModel = get_user_model() try: user = UserModel.objects.get(user_email=user_email) if user.check_password(password): login(request, user) return redirect('home') # 替换成你的主页URL名称 else: form.add_error('password', '密码输入错误') except UserModel.DoesNotExist: form.add_error('user_email', '该邮箱未注册') else: form = LoginForm() return render(request, 'login.html', {'form': form})
最后提醒一句:Django的AbstractBaseUser已经帮你处理了密码哈希、登录状态等核心逻辑,尽量不要自己去覆盖这些内置字段,否则很容易踩坑!
内容的提问来源于stack exchange,提问作者aak

