Django中表单提交按钮无法通过JavaScript触发提交的问题
问题:提交邮件按钮无响应,无法触发
submit_mail函数 我在Django项目中实现邮件功能,使用以下HTML和JavaScript代码,但点击提交按钮后没有任何反应,浏览器控制台也未显示错误,无法触发submit_mail函数。
HTML代码
{% extends "mail/layout.html" %} {% load static %} {% block body %} <h2>{{ request.user.email }}</h2> <button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button> <button class="btn btn-sm btn-outline-primary" id="compose">Compose</button> <button class="btn btn-sm btn-outline-primary" id="sent">Sent</button> <button class="btn btn-sm btn-outline-primary" id="archived">Archived</button> <a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a> <hr> <div id="emails-view"> </div> <div id="compose-view"> <h3>New Email</h3> <form id="compose-form"> <div class="form-group"> From: <input disabled class="form-control" value="{{ request.user.email }}"> </div> <div class="form-group"> To: <input id="compose-recipients" class="form-control"> </div> <div class="form-group"> <input class="form-control" id="compose-subject" placeholder="Subject"> </div> <textarea class="form-control" id="compose-body" placeholder="Body"></textarea> <input type="submit" class="btn btn-primary"/> </form> </div> {% endblock %} {% block script %} <script src="{% static 'mail/inbox.js' %}"></script> {% endblock %}
JavaScript代码(原代码)
document.addEventListener('DOMContentLoaded', function() { // Use buttons to toggle between views document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox')); document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent')); document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive')); document.querySelector('#compose').addEventListener('click', compose_email); document.querySelector('#compose-form').addEventListener('submit', submit_mail); // By default, load the inbox load_mailbox('inbox'); }); // COMPOSE EMAIL function compose_email() { // Show compose view and hide other views document.querySelector('#emails-view').style.display = 'none'; document.querySelector('#compose-view').style.display = 'block'; // Clear out composition fields document.querySelector('#compose-recipients').value = ''; document.querySelector('#compose-subject').value = ''; document.querySelector('#compose-body').value = ''; } // SENT EMAIL function submit_mail(event) { // Post email to API route fetch('/emails' , { method: 'POST', body: JSON.stringify({ recipients: document.querySelector('#compose-recipients').value, subject: document.querySelector('#compose-subject').value, body: document.querySelector('#compose-body').value }) }) .then(response => load_mailbox('sent')); }
问题原因及修复方案
核心问题
- 表单默认提交行为未阻止:点击submit按钮时,浏览器会自动执行表单默认提交动作(刷新页面/跳转),导致JavaScript代码还没完成请求就被中断,看起来像没触发函数。
- 缺少必要请求头:Django需要CSRF令牌验证POST请求,且未声明请求体为JSON格式,服务器无法正确解析数据。
- 无错误处理:原代码未处理请求失败的情况,无法排查问题。
修复后的完整JavaScript代码
document.addEventListener('DOMContentLoaded', function() { // 切换视图按钮绑定事件 document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox')); document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent')); document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive')); document.querySelector('#compose').addEventListener('click', compose_email); document.querySelector('#compose-form').addEventListener('submit', submit_mail); // 默认加载收件箱 load_mailbox('inbox'); }); // 撰写邮件 function compose_email() { // 切换显示视图 document.querySelector('#emails-view').style.display = 'none'; document.querySelector('#compose-view').style.display = 'block'; // 清空输入框 document.querySelector('#compose-recipients').value = ''; document.querySelector('#compose-subject').value = ''; document.querySelector('#compose-body').value = ''; } // 发送邮件 function submit_mail(event) { // 1. 阻止表单默认提交行为 event.preventDefault(); // 2. 发送POST请求到后端 fetch('/emails', { method: 'POST', // 添加必要请求头 headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') }, body: JSON.stringify({ recipients: document.querySelector('#compose-recipients').value, subject: document.querySelector('#compose-subject').value, body: document.querySelector('#compose-body').value }) }) .then(response => { // 处理响应状态 if (response.ok) { load_mailbox('sent'); } else { alert('发送失败,请检查收件人格式是否正确'); } }) .catch(error => { // 捕获请求错误 console.error('请求出错:', error); alert('发送出错,请稍后重试'); }); } // 辅助函数:获取Django的CSRF令牌 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; }
修复说明
event.preventDefault():阻止浏览器默认的表单提交动作,确保JavaScript代码完整执行。- 添加
headers:包含Content-Type声明JSON格式,以及X-CSRFToken通过Django的CSRF验证。 - 新增
getCookie函数:从浏览器Cookie中获取CSRF令牌,这是Django处理POST请求的必要步骤。 - 完善错误处理:通过
response.ok判断请求是否成功,catch捕获网络错误,给用户明确提示,同时方便调试。
内容的提问来源于stack exchange,提问作者kroma235
相关产品推荐
相关产品推荐

