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

使用Vanilla JS+AJAX提交Django表单需点击两次提交按钮问题求解

问题根源排查

核心原因是CKEditor编辑器没有在表单提交前实时将内容同步到对应的原生textarea元素:

  • 第一次点击提交时,FormData读取的是未更新的原始textarea值,提交到Django后form.is_valid()校验失败(content字段为空或者不符合规则),所以视图直接返回了200状态的表单渲染结果,没有存入数据库。
  • 第一次提交操作触发了CKEditor的内容同步逻辑,第二次提交时textarea已经写入了正确的内容,校验通过就返回201创建成功。

解决方法

1. 提交前手动同步CKEditor内容到textarea

修改你的JS提交事件逻辑,在构造FormData之前先触发CKEditor的内容同步:

const handlePostSubmit = function(e){
    e.preventDefault()    
    // 新增:同步所有CKEditor实例的内容到对应的textarea
    for (let instance in CKEDITOR.instances) {
        CKEDITOR.instances[instance].updateElement();
    }
    const myForm = e.target
    const myFormData = new FormData(myForm)
    // 后续原有逻辑保持不变
    const url = myForm.getAttribute("action")
    const method = myForm.getAttribute("method")
    const xhr = new XMLHttpRequest()

    xhr.open(method, url)
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
    xhr.onload = function() {
        const serverResponse = xhr.response
        console.log(serverResponse, xhr.status)
        const postsEl = document.getElementById("posts")
        loadPosts(postsEl)         
    }
    xhr.send(myFormData)   
}

2. 可选优化:增加表单校验失败的提示

你可以在xhr.onload里加状态判断,方便后续排查问题:

xhr.onload = function() {
    console.log(xhr.response, xhr.status)
    if(xhr.status === 201) {
        loadPosts(document.getElementById("posts"))
        // 可选:提交成功后清空表单
        postCreateFormEl.reset()
    } else {
        // 校验失败时输出错误信息,方便调试
        console.log("表单提交失败,请检查字段是否符合要求")
    }
}

额外说明

你代码里设置的HTTP_X_REQUESTED_WITH请求头是多余的,Django识别AJAX请求只需要X-Requested-With: XMLHttpRequest即可,保留后者就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 17:15:07