Django登录API问题:Postman请求报错且user打印返回None
问题分析与修复方案
核心问题点
- 请求方法错误:使用
GET请求提交登录数据,request.data无法获取POST体中的参数,且GET请求会将密码暴露在URL中,存在安全风险。 - 认证逻辑错误:Django默认的
authenticate方法通过username和password验证身份,而非email,直接传入email=email无法匹配用户。 - 序列化器字段问题:
password字段未设置write_only=True,导致无法正确获取输入的密码值;且应使用validated_data而非data获取验证后的参数。
具体修复步骤
1. 修改视图类的请求方法与认证逻辑
将get方法改为post,并调整用户认证的逻辑:
class UserLoginView(APIView): permission_classes = (AllowAny,) serializer_class = UserLoginSerializer # 替换get为post方法,符合登录请求的语义 def post(self, request, format=None): serializer = UserLoginSerializer(data=request.data) if serializer.is_valid(raise_exception=True): # 使用validated_data获取验证后的参数,比data更可靠 email = serializer.validated_data.get('email') password = serializer.validated_data.get('password') # 先通过邮箱查询对应用户 try: user = User.objects.get(email=email) except User.DoesNotExist: return Response({'msg': 'Email or Password Does not match'}, status=status.HTTP_404_NOT_FOUND) # 用username和密码执行认证 authenticated_user = authenticate(username=user.username, password=password) if authenticated_user is not None: login(request, authenticated_user) return Response({'msg': 'Login Success'}, status=status.HTTP_200_OK) else: return Response({'msg': 'Email or Password Does not match'}, status=status.HTTP_404_NOT_FOUND) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
2. 修正序列化器的密码字段
显式设置password为只写字段,确保能正确接收输入的密码:
class UserLoginSerializer(serializers.ModelSerializer): email = serializers.EmailField(max_length=200) # 设置password为只写字段,避免序列化返回密码,同时确保能获取输入值 password = serializers.CharField(write_only=True) class Meta: model = User fields = ['email', 'password']
3. Postman请求调整
- 请求方法改为
POST - 请求体选择
raw->JSON,输入格式示例:
{ "email": "test@example.com", "password": "your-password" }
可选优化:自定义邮箱认证后端(推荐)
如果希望直接用邮箱+密码认证,无需手动查询用户,可以自定义认证后端:
在项目根目录创建backends.py文件:
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User class EmailBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: # 用传入的username参数匹配邮箱 user = User.objects.get(email=username) except User.DoesNotExist: return None # 验证密码正确性 if user.check_password(password): return user return None
在settings.py中配置认证后端:
AUTHENTICATION_BACKENDS = [ 'your_project_name.backends.EmailBackend', 'django.contrib.auth.backends.ModelBackend', ]
此时视图中的认证逻辑可简化为:
user = authenticate(request, username=email, password=password)
内容的提问来源于stack exchange,提问作者Yashraj Sharma
相关产品推荐
相关产品推荐

