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

DRF获取Token登录:如何将默认用户名替换为邮箱?

问题分析与解决方案

问题根源

  1. 错误使用ModelSerializer:你用ModelSerializer实现登录序列化器时,它会自动应用AuthUser模型的字段约束(比如邮箱唯一性校验),导致传入已注册邮箱时触发“该邮箱已存在用户”的错误——这完全不符合登录场景的需求。
  2. validate方法未传递用户对象:你的校验方法仅返回了邮箱和密码,没有将验证通过的用户对象存入validated_data,后续视图无法正确获取用户实例。
  3. 多余的create方法:登录逻辑不需要创建新用户,该方法属于冗余代码,还可能引发逻辑混淆。

修改后的代码实现

1. 自定义登录序列化器

from rest_framework import serializers
from .models import AuthUser

class AuthTokenSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField(write_only=True)

    def validate(self, data):
        email = data.get('email')
        password = data.get('password')

        if not email or not password:
            raise serializers.ValidationError("请提供邮箱和密码")
        
        user = AuthUser.objects.filter(email=email).first()
        if not user:
            raise serializers.ValidationError("该邮箱未注册")
        
        if not user.check_password(password):
            raise serializers.ValidationError("密码错误")
        
        # 将验证通过的用户对象存入validated_data,供视图调用
        data['user'] = user
        return data

2. 自定义登录视图

from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.response import Response
from rest_framework.authtoken.models import Token
from .serializers import AuthTokenSerializer

class AuthLoginUser(ObtainAuthToken):
    serializer_class = AuthTokenSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        
        return Response({
            'token': token.key,
            'first_name': user.first_name,
            'last_name': user.last_name,
            'email': user.email,
            'role': user.role
        })

3. URL配置(保持你的修改)

urlpatterns = [
    # ... 其他路由
    path('login/', views.AuthLoginUser.as_view()),
]

关键修改说明

  • 改用Serializer替代ModelSerializer:仅定义登录所需的字段,避免模型自带的唯一性校验干扰登录流程。
  • 在validate方法中传递用户对象:验证通过后将用户实例存入validated_data,确保视图能正确获取用户信息生成Token。
  • 移除冗余的create方法:登录逻辑不需要创建新用户,删除后避免逻辑混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:33:17