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

Django REST Framework登录接口报‘邮箱已存在’错误求助

问题原因与解决方案

错误原因

你使用ModelSerializer实现登录逻辑,但ModelSerializer会自动继承User模型的字段验证规则。由于你的User模型中email字段设置了unique=True,序列化器在调用is_valid()时,会默认执行「检查email是否已存在」的验证——这是注册场景的逻辑,完全不符合登录需求(登录需要验证已存在的用户身份,而非创建新用户)。

修复方案

方案1:改用基础Serializer(推荐)

登录不需要创建/更新模型实例,使用基础Serializer可彻底避免继承模型的多余验证规则:

from rest_framework import serializers
from django.contrib.auth import authenticate

class UserLoginSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    password = serializers.CharField(write_only=True, required=True)
    full_name = serializers.CharField(read_only=True)
    tokens = serializers.CharField(read_only=True)
    id = serializers.IntegerField(read_only=True)
    is_superuser = serializers.BooleanField(read_only=True)
    is_seller = serializers.BooleanField(read_only=True)
    created_at = serializers.DateTimeField(read_only=True)
    profile_pic = serializers.ImageField(read_only=True)

    def validate(self, data):
        email = data.get('email')
        password = data.get('password')
        
        user = authenticate(email=email, password=password)
        if not user:
            raise serializers.ValidationError("无效的邮箱或密码")
        
        # 将用户信息补充到返回数据中
        data['id'] = user.id
        data['full_name'] = user.get_name()
        data['tokens'] = user.get_token()
        data['is_superuser'] = user.is_superuser
        data['is_seller'] = user.is_seller
        data['created_at'] = user.created_at
        data['profile_pic'] = user.profile_pic
        return data

方案2:保留ModelSerializer并移除Unique验证

如果坚持使用ModelSerializer,需覆盖email字段,手动移除其自带的唯一性验证:

class UserLoginSerializer(serializers.ModelSerializer):
    full_name: str = serializers.CharField(source='get_name', read_only=True)
    tokens: str  = serializers.CharField(source='get_token', read_only=True)
    
    # 覆盖email字段,取消唯一性验证
    email = serializers.EmailField(required=True)
    
    class Meta:
        model = User
        fields = (
            'id',
            'full_name',
            'email',
            'password',
            'is_superuser',
            'is_seller',
            'created_at',
            'profile_pic',
            'tokens' 
        )
        extra_kwargs = {
            'password' : {'write_only':True, 'required': True},
            'id': {'read_only': True},
            'is_superuser': {'read_only': True},
            'is_seller': {'read_only': True},
            'created_at': {'read_only': True},
            'profile_pic': {'read_only': True}
        }

    def validate(self, data: dict) -> dict:
        email: str = data.get('email', '')
        password: str = data.get('password', '')
        user = authenticate(email=email, password=password)
        
        if not user:
            raise serializers.ValidationError("无效的登录凭证")
            
        data['tokens'] = user.get_token()
        return data

注意:两种方案都必须在validate方法中处理用户验证失败的情况,避免user为None时触发AttributeError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:56:07