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

Django自定义用户登录API报“无效邮箱或密码”错误求助

问题分析与解决方法

核心错误原因

  • 自定义User模型冗余字段导致密码未哈希存储:继承AbstractBaseUser的模型无需手动添加password字段,该基类已内置密码哈希存储逻辑。手动添加的password = models.CharField(max_length=100)会让注册时明文密码直接存入数据库,而check_password()方法仅验证哈希值,自然匹配失败。
  • 用户注册时未正确调用密码哈希方法:UserRegistrationSerializer的create方法直接用User.objects.create()创建用户,未调用set_password()哈希密码,导致数据库存储明文密码。
  • 视图中存在模型导入冲突:views.py同时导入自定义User和Django自带User模型,造成代码引用混乱。

修复步骤

1. 修正models.py中的User模型

移除手动添加的password字段,保留基类内置的密码逻辑:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin

class Address(models.Model):
    TYPE_CHOICES = [
        ('office', 'Office'),
        ('factory', 'Factory')
    ]
    type = models.CharField(max_length=10, choices=TYPE_CHOICES)
    addressLine1 = models.CharField(max_length=100)
    addressLine2 = models.CharField(max_length=100, blank=True, null=True)
    addressLine3 = models.CharField(max_length=100, blank=True, null=True)
    postal_code = models.CharField(max_length=20)
    state = models.CharField(max_length=100)
    city = models.CharField(max_length=100)
    country = models.CharField(max_length=100)

class UserManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError('The Email field must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, username=username)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(email, username, password)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

class User(AbstractBaseUser):
    username = models.CharField(max_length=100, unique=True)
    email = models.EmailField(unique=True)
    # 移除手动添加的password字段
    phone = models.CharField(max_length=20)
    address = models.OneToOneField(Address, on_delete=models.CASCADE)
    business_category = models.CharField(max_length=100)
    number_of_employees = models.CharField(max_length=50)
    usage_description = models.TextField(blank=True)
    otp = models.CharField(max_length=6, null=True, blank=True)
    is_active = models.BooleanField(default=False)
    is_verified = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

2. 修正serializers.py中的UserRegistrationSerializer

创建用户时调用set_password()哈希密码,并设置密码为仅写入字段:

from rest_framework import serializers
from .models import User, Address

# 其他序列化器保持不变

class UserRegistrationSerializer(serializers.ModelSerializer):
    address = AddressSerializer()

    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        address_data = validated_data.pop('address')
        address = Address.objects.create(**address_data)
        user = User.objects.create(address=address, **validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user

3. 修正views.py中的模型导入冲突

删除Django自带User模型的导入,仅保留自定义模型:

# 移除该行:from django.contrib.auth.models import User
from .models import User
# 其他导入保持不变

4. 重新迁移数据库

修改模型后需更新数据库结构:

python manage.py makemigrations
python manage.py migrate

5. 重新注册测试用户

删除之前注册的旧用户(密码为明文存储),重新注册新用户确保密码以哈希形式存储。


验证修复效果

重新发起登录请求,user.check_password(password)会正确验证哈希密码,登录成功后将返回Token及成功提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 00:29:50