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

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默认端口
]

三、完整流程验证

  1. 前端输入用户名和密码,点击提交发送POST请求到/user/login/
  2. 后端验证请求体格式与用户名密码合法性
  3. 验证成功后返回Token,前端将Token存入localStorage
  4. 后续前端请求时,自动在请求头携带Authorization: Token <你的token>,即可通过Token认证

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:31:30