You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义用户模型的注册与登录技术问题求助

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:19:01