ReactJS对接Django登录功能遇400错误,求解决方法
解决React + Django登录的400 Bad Request错误及完整实现
一、核心错误原因及修复
1. 前端Axios请求格式错误
你在前端用JSON.stringify()包裹请求体,导致后端无法正确解析JSON数据。Axios默认会自动将JavaScript对象序列化为JSON,并设置Content-Type: application/json,不需要手动调用JSON.stringify()。
修改前端登录提交代码:
const onSubmit = e =>{ e.preventDefault() api .post(`user/login/`, {username, password}) // 直接传对象,无需stringify .then(({data}) =>{ console.log(data) // 登录成功后保存token到本地存储 localStorage.setItem('authToken', data.token) // 全局设置axios请求头,后续请求自动携带token api.defaults.headers.common['Authorization'] = `Token ${data.token}` }) .catch(err => { console.error(err.response.data) // 打印具体错误信息,便于排查 }) }
2. Django序列化器配置问题
LoginSerializer使用ModelSerializer时,password字段默认是可读可写,但登录场景只需要接收密码,不需要返回该字段;同时Django User模型的密码字段有默认校验规则,直接使用ModelSerializer可能导致验证失败。
修改serializer.py:
from rest_framework import serializers from django.contrib.auth.models import User class LoginSerializer(serializers.Serializer): # 改用Serializer更灵活,无需关联模型所有字段 username = serializers.CharField(required=True) password = serializers.CharField(required=True, write_only=True) # 若坚持使用ModelSerializer,需显式设置password为仅写入 # class LoginSerializer(serializers.ModelSerializer): # class Meta: # model = User # fields = ['username', 'password'] # extra_kwargs = { # 'password': {'write_only': True} # }
3. 后端视图的Token返回问题
你配置了TokenAuthentication,但登录成功后未返回Token,前端无法获取认证凭证。需要生成并返回Token给前端。
修改view.py:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.authentication import TokenAuthentication from rest_framework.permissions import AllowAny from django.contrib.auth import authenticate, login from rest_framework.authtoken.models import Token # 导入Token模型 from .serializers import LoginSerializer class Login(APIView): authentication_classes = (TokenAuthentication,) permission_classes = (AllowAny,) def post(self, request): serializer = LoginSerializer(data=request.data) if serializer.is_valid(raise_exception=True): # 用validated_data获取校验后的数据,比raw data更可靠 username = serializer.validated_data.get('username') password = serializer.validated_data.get('password') # 传入request参数,适配部分认证后端要求 user = authenticate(request=request, username=username, password=password) if user is not None: login(request, user) # 获取或创建用户对应的Token token, created = Token.objects.get_or_create(user=user) return Response({ "msg": "登录成功", "token": token.key # 返回Token给前端 }, status=status.HTTP_200_OK) else: return Response( { "errors": { "non_field_errors": ["用户名或密码无效"] } }, status=status.HTTP_401_UNAUTHORIZED # 用401更符合HTTP规范,404表示资源不存在 ) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
二、额外配置检查
1. Django REST Framework Token配置
确保settings.py中已添加相关配置:
INSTALLED_APPS = [ # ... 'rest_framework', 'rest_framework.authtoken', # 必须添加 # ... ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], }
运行迁移创建Token表:
python manage.py migrate
2. 跨域(CORS)配置
解决React与Django的跨域问题,安装并配置django-cors-headers:
pip install django-cors-headers
修改settings.py:
INSTALLED_APPS = [ # ... 'corsheaders', # ... ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 需放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', # ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", # React默认端口 ]
三、完整流程验证
- 前端输入用户名和密码,点击提交发送POST请求到
/user/login/ - 后端验证请求体格式与用户名密码合法性
- 验证成功后返回Token,前端将Token存入localStorage
- 后续前端请求时,自动在请求头携带
Authorization: Token <你的token>,即可通过Token认证
内容的提问来源于stack exchange,提问作者pygirl
相关产品推荐
相关产品推荐

