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

Django升级至最新版后提交表单出现CSRF验证失败(403)求助

Django升级后CSRF验证失败问题解决

问题背景

基于Django 3.8开发的答题应用,升级到最新版本后,学生提交答案时抛出CSRF verification failed. Request aborted错误,提示CSRF token缺失。已添加{% csrf_token %}标签、配置CsrfViewMiddleware、尝试@csrf_protect装饰器均无效。

错误原因分析

  1. 模板冗余CSRF输入:模板同时存在{% csrf_token %}和手动硬编码的固定值csrfmiddlewaretoken隐藏输入,静态token无法随请求动态更新,导致验证失效。
  2. JS函数逻辑错误:saveAns函数中使用if(ele[i].type="radio")(赋值运算符)而非判断运算符===,会强制将所有input元素的type改为radio,包括{% csrf_token %}生成的隐藏输入框,破坏了CSRF token的提交结构。
  3. 视图请求处理不规范:视图未限定仅处理POST请求,且依赖Cookie获取答案的方式不符合Django CSRF验证的规范流程。

解决方案

1. 清理模板冗余代码

移除模板中手动添加的固定CSRF token输入,保留{% csrf_token %}即可,该标签会自动生成动态有效的token:

<!-- 删除以下硬编码内容 -->
<!-- <input type="hidden" name="csrfmiddlewaretoken" value="C24rUotmdHawVQJL3KrqiWxvti8UffOFYUc8TRbZtLt36AVLdP3jbkzUVe3beRAa"> -->

2. 修复JS函数判断逻辑

将saveAns中的赋值操作改为全等判断,避免修改非radio输入的类型,同时确保函数返回true以保证表单正常提交:

function saveAns(){  
    var ele = document.getElementsByTagName('input'); 
    for(i = 0; i < ele.length; i++) { 
        // 改为全等判断 ===
        if(ele[i].type === "radio") { 
            if(ele[i].checked){        
              setCookie(ele[i].name,ele[i].value,3)
            }
        } 
    } 
    return true;
}

3. 规范视图请求处理

更新视图,仅在POST请求时处理逻辑,同时建议直接从request.POST获取答案(更安全,避免Cookie依赖):

from django.shortcuts import HttpResponseRedirect, get_object_or_404
from django.contrib.auth.decorators import login_required

@login_required
def calculate_marks_view(request):
    # 仅处理POST请求
    if request.method == 'POST':
        course_id = request.COOKIES.get('course_id')
        if course_id is None:
            return HttpResponseRedirect('/student/')
        
        course = get_object_or_404(QMODEL.Course, id=course_id)
        total_marks = 0
        questions = QMODEL.Question.objects.filter(course=course)
        
        # 从request.POST获取选中答案,替代Cookie方式
        for idx, question in enumerate(questions, 1):
            selected_ans = request.POST.get(str(idx))
            if selected_ans == question.answer:
                total_marks += question.marks
        
        student = get_object_or_404(Student, user_id=request.user.id)
        result = QMODEL.Result.objects.create(
            marks=total_marks,
            exam=course,
            student=student
        )
        
        return HttpResponseRedirect('view-result')
    # GET请求重定向到考试页面
    return HttpResponseRedirect('/student/exam/')

额外注意事项

  • 确保渲染表单的视图通过render(request, template_name, context)传递request对象,这样{% csrf_token %}才能生成正确的token。
  • 升级Django后,检查CSRF_COOKIE_SECURE、CSRF_COOKIE_HTTPONLY等设置,若站点使用HTTPS,建议开启CSRF_COOKIE_SECURE。

内容的提问来源于stack exchange,提问作者The Dance Studio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:53:25