CKEDITOR对话框onOk事件调用AJAX出现404错误求助
你遇到的这个404问题核心原因很明确:Django的模板标签(比如{% url %}和{{ csrf_token }})只会在后端渲染HTML模板时被解析,而你的CKEditor对话框JS代码如果是放在单独的.js文件里,后端根本不会处理里面的模板标签。
浏览器拿到的JS代码里,{% url 'util:upload_doc_to_s3' %}就是原始的字符串,没有被替换成实际的URL。当你把这个字符串作为AJAX的url参数时,因为它是相对路径格式(没有以/开头),浏览器会自动把它拼在当前页面的路径后面,也就是util/product_tab/edit/cfd/13/加上{% url 'util:upload_doc_to_s3' %},再经过URL编码就变成了你看到的%7B%%20url%20 'util:upload_doc_to_s3'%20%20%%7D,自然找不到对应的路由,返回404。
另外,你的csrf_token也会遇到同样的问题——{{ csrf_token }}不会被解析成实际的令牌值,这还会导致后续的CSRF验证失败。
根据你的JS代码存放位置,有两种常见的解决方式:
1. 如果JS代码内嵌在Django模板文件中
如果这段CKEditor的代码是写在.html模板的<script>标签里,那只需要确保模板标签能被正确解析:
- 确认你的模板被Django视图正确渲染,上下文没有问题
- 把AJAX的
url改成以/开头的绝对路径(或者依赖{% url %}生成正确的绝对路径),同时修正csrf_token的传递:
👉 额外提醒:如果onOk: function () { $.ajax({ url: "{% url 'util:upload_doc_to_s3' %}", // 现在会被后端解析成正确的URL type: "POST", data: { // 注意:如果fileObj是文件对象,直接这么传是无效的,需要用FormData // fileObj: fileObj, csrfmiddlewaretoken: '{{ csrf_token }}' // 同样会被解析成实际令牌 }, success: function(json) { console.log('done triggered'); console.log(json); // 这里你之前写的是response,参数名是json,要对应 }, error: function(xhr, errmsg, err) { console.log('fail triggered'); } }); }fileObj是文件对象,你需要用FormData来传递,否则文件无法正确上传,示例:var formData = new FormData(); formData.append('fileObj', fileObj); formData.append('csrfmiddlewaretoken', '{{ csrf_token }}'); $.ajax({ url: "{% url 'util:upload_doc_to_s3' %}", type: "POST", data: formData, processData: false, // 必须设置,不然jQuery会自动处理FormData导致错误 contentType: false, // 必须设置,让浏览器自动设置正确的Content-Type // ... 其他回调函数 });
2. 如果JS代码放在单独的.js文件中
单独的JS文件不会被Django模板引擎处理,所以需要把动态生成的URL和csrf_token从模板传递到JS里:
- 第一步:在模板的
<script>标签里定义全局变量(放在引入你的JS文件之前):<script> // 把Django生成的URL和csrf_token暴露给全局 window.uploadConfig = { url: "{% url 'util:upload_doc_to_s3' %}", csrfToken: "{{ csrf_token }}" }; </script> <script src="/path/to/your-ckeditor-script.js"></script> - 第二步:在你的CKEditor JS代码里使用这些全局变量:
onOk: function () { var formData = new FormData(); formData.append('fileObj', fileObj); formData.append('csrfmiddlewaretoken', window.uploadConfig.csrfToken); $.ajax({ url: window.uploadConfig.url, // 使用全局变量里的正确URL type: "POST", data: formData, processData: false, contentType: false, success: function(json) { console.log('done triggered'); console.log(json); }, error: function(xhr, errmsg, err) { console.log('fail triggered'); } }); }
这样就能保证AJAX请求的URL是正确的http://localhost:8000/util/upload_doc_to_s3/,不会再出现404错误了。
内容的提问来源于stack exchange,提问作者Boon Yao Lee

