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

React表单调用DRF接口发邮件出现400错误,寻求排查方案

问题:React调用API返回400错误,API页面测试正常

我尝试通过以下API发送表单数据:React应用调用时返回400错误,但直接在API接口页面测试能正常运行。对比请求负载发现React应用没带CSRF Token,但之前用模型序列化器时不需要这个Token。怀疑问题出在序列化器,但找不到具体原因,请问400错误可能是什么原因?


sendEmail.js

const testmessage = "This is a test message"
const testemail = "dsfds@dsfg.de"
const clientnametest = "name"
function sendProposal(values) {
    console.log("start sending proposal...");
    setSendProp(true)

    const data = new FormData()
    data.append("Clientname", clientnametest || "");
    data.append("Sender", testemail || "");
    data.append("Message", testmessage || "");

    axios.post(API.email.proposal, data, {
        headers: {
            "Authorization": `Bearer ${accessToken}`,
            'Accept' : 'application/json',
        },
        withCredentials: true,
    })
    .then(res => {})
    .finally(() => {                
        setSendProp(false)
    })

    success()
}

views.py

class ProposalEmailView(APIView):
    
    permission_classes = [IsAuthenticated]
    serializer_class = ProposalEmailSerializer
    
    def post(self, request, *args, **kwargs):
        serializer_class = ProposalEmailSerializer(data=request.data)
        if serializer_class.is_valid():
             data = serializer_class.validated_data
             ClientName = data.get('ClientName')
             Sender = data.get('Sender')
             Message = data.get('Message')
             send_mail('Contact Form mail from ' + ClientName,
                       Message, Sender, ['test@test.test'],)
            
             return Response({"success": "Sent"}, status=status.HTTP_200_OK)
        return Response({"error": "Failed"}, status=status.HTTP_400_BAD_REQUEST)

serializers.py

class ProposalEmailSerializer(serializers.Serializer):
    ClientName = serializers.CharField()
    Sender = serializers.EmailField()
    Message = serializers.CharField()

可能的原因及解决方法

1. 字段名大小写不匹配

React代码中用data.append("Clientname", ...),但序列化器定义的字段是ClientName(第二个字母N大写),字段名大小写完全不一致会导致序列化器验证失败,直接返回400错误。这是最核心的问题——API页面测试时你可能手动输入了正确的字段名,而React代码里写错了。

2. 序列化器未返回具体错误信息

当前视图中验证失败仅返回{"error": "Failed"},无法看到具体错误细节。建议修改视图,返回序列化器的错误详情,快速定位问题:

return Response(serializer_class.errors, status=status.HTTP_400_BAD_REQUEST)

3. CSRF Token问题(次要排查项)

虽然使用了Bearer Token认证,但Django默认对表单提交会检查CSRF Token。如果后端未配置CSRF_COOKIE_HTTPONLY = False,需要手动获取CSRF Token并添加到请求头:

// 获取CSRF Token
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
const csrftoken = getCookie('csrftoken');

// 在axios请求头中添加
headers: {
    "Authorization": `Bearer ${accessToken}`,
    'Accept' : 'application/json',
    'X-CSRFToken': csrftoken
},

4. FormData格式兼容性(低概率)

axios发送FormData时会自动设置Content-Type: multipart/form-data,但可以在浏览器开发者工具中检查请求头是否正确,确保Django能正常解析FormData数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:25:40