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

Django自定义Trainer用户模型登录失败问题求助

解决Django自定义Trainer用户模型的登录问题

问题描述

我在Django的TRAINERS应用中创建了自定义Trainer用户模型,用户注册功能可正常使用,但登录时始终提示Please enter a correct username and password. Note that both fields may be case-sensitive.。尝试了一段登录视图代码仍无法解决,请问如何在登录时指定Trainer用户模型?

Trainer用户模型代码

class Trainer(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=30, unique=True)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    bio = models.TextField(blank=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = TrainerManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name']

    groups = models.ManyToManyField(Group, related_name='trainer_groups', blank=True)
    user_permissions = models.ManyToManyField(Permission, related_name='trainer_user_permissions', blank=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

尝试的登录视图代码

def trainer_login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            email = form.cleaned_data.get('username')  # Use email as the username field
            password = form.cleaned_data.get('password')
            user = authenticate(request, email=email, password=password)

            if user is not None:
                login(request, user)
                messages.success(request, 'Login successful.')
                # Redirect to the desired page after login
                return redirect('dashboard')  # Change 'dashboard' to your desired URL name
            else:
                messages.error(request, 'Invalid email or password.')
    else:
        form = AuthenticationForm()

    return render(request, 'trainer_login.html', {'form': form})

问题原因

  1. 默认表单绑定原生User模型:AuthenticationForm默认关联Django自带的User模型,即使手动处理邮箱和密码,表单验证逻辑仍基于原生User,无法匹配自定义Trainer模型。
  2. 未指定默认用户模型:若项目配置中未声明默认用户模型为Trainer,authenticate方法无法正确识别自定义模型的认证规则。
  3. 用户管理器可能存在实现缺陷:如果TrainerManager未正确实现密码哈希逻辑,注册用户的密码会以明文存储,导致登录验证失败。

解决方案

1. 配置项目默认用户模型

在项目settings.py中添加以下配置,指定默认用户模型为Trainer:

AUTH_USER_MODEL = 'trainers.Trainer'

注意:此配置需在项目初始化时设置,后续修改可能引发数据库迁移问题。

2. 完善TrainerManager实现

确保TrainerManager正确继承BaseUserManager并实现密码哈希逻辑,示例代码:

from django.contrib.auth.base_user import BaseUserManager

class TrainerManager(BaseUserManager):
    def create_user(self, email, username, first_name, last_name, password=None, **extra_fields):
        if not email:
            raise ValueError('必须提供邮箱地址')
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            username=username,
            first_name=first_name,
            last_name=last_name,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, first_name, last_name, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('超级用户必须设置is_staff=True')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('超级用户必须设置is_superuser=True')

        return self.create_user(email, username, first_name, last_name, password, **extra_fields)

3. 自定义登录表单

创建关联Trainer模型的登录表单,替换默认AuthenticationForm:

from django.contrib.auth.forms import AuthenticationForm
from .models import Trainer

class TrainerAuthenticationForm(AuthenticationForm):
    class Meta:
        model = Trainer
        fields = ('email', 'password')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['username'].label = '邮箱'

4. 更新登录视图

修改视图使用自定义表单,简化认证逻辑:

from django.contrib.auth import login, messages
from django.shortcuts import render, redirect
from .forms import TrainerAuthenticationForm

def trainer_login(request):
    if request.method == 'POST':
        form = TrainerAuthenticationForm(request, data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
            messages.success(request, '登录成功')
            return redirect('dashboard')
        else:
            messages.error(request, '邮箱或密码无效')
    else:
        form = TrainerAuthenticationForm()
    return render(request, 'trainer_login.html', {'form': form})

5. 模板适配(可选)

确保模板中表单输入框的name属性为username(因Trainer模型USERNAME_FIELD设为email,表单会自动映射),示例模板片段:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">登录</button>
</form>

内容的提问来源于stack exchange,提问作者Persius_jackson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:53:22