Django表单优化:用本地存储替代后端数据,实现无重载更新
无刷新实现可增删表单模块(基于本地存储)
我是Django初学者,开发了一个带表单的网页,表单包含预设值,用户需补充其余内容,其中教育经历、工作经验、技术技能属于可增删的多段模块,最终数据以JSON格式存储。当前点击添加/删除按钮时,前端能完成数据操作,但必须发送完整JSON至后端并重载页面才能更新显示。现需实现无需发送完整JSON到后端,通过本地存储完成表单更新且避免页面重载,技术栈为Django+HTML+JavaScript。
核心思路
- 本地存储初始化:页面首次加载时,将后端传递的初始
resume数据存入localStorage,作为前端数据的唯一数据源 - 动态渲染模块:编写通用渲染函数,读取
localStorage中的数据,动态生成对应的表单DOM元素 - 增删操作仅修改本地存储:点击添加/删除按钮时,直接修改
localStorage内的对应数据,再调用渲染函数更新页面,无需请求后端或重载 - 最终统一提交:用户完成所有编辑后,一次性将
localStorage中的完整数据提交至后端存储
修改后的代码实现
1. HTML部分(技术技能模块)
保留基础结构,将Django模板循环渲染改为JS动态生成:
<h2>Technical Skills</h2> <!-- 动态渲染的技术技能模块插入容器 --> <div id="tech-skills-container"></div> <div id="techskill"> <button type="button" onclick="addTechSkill()">Add Technical Skill</button> </div> <!-- Django安全传递初始数据 --> {{ resume|json_script:"initial-resume-data" }}
2. JavaScript部分
初始化与渲染函数
// 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', function() { // 从Django模板获取初始数据 const initialResumeData = JSON.parse(document.getElementById('initial-resume-data').textContent); // 初始化本地存储(仅当无数据时) if (!localStorage.getItem('resumeData')) { localStorage.setItem('resumeData', JSON.stringify(initialResumeData)); } // 首次渲染技术技能模块 renderTechSkills(); }); // 渲染技术技能模块 function renderTechSkills() { const container = document.getElementById('tech-skills-container'); const resumeData = JSON.parse(localStorage.getItem('resumeData')); const techSkills = resumeData.techskill || []; // 清空容器后重新渲染 container.innerHTML = ''; techSkills.forEach((item, index) => { const fieldset = document.createElement('fieldset'); fieldset.innerHTML = ` <div class="tech"></div> <legend>Technical Skill ${index + 1}</legend> <label for="skillName${index + 1}">Skill Name:</label> <input type="text" id="skillName${index + 1}" name="skillName${index + 1}" value="${item.skill_name || ''}"><br><br> <label for="expertise${index + 1}">Expertise:</label> <input type="text" id="expertise${index + 1}" name="expertise${index + 1}" value="${item.expertise || ''}"><br><br> <label for="yearOfExp${index + 1}">Year of Experience:</label> <input type="text" id="yearOfExp${index + 1}" name="yearOfExp${index + 1}" value="${item.year_of_exp || ''}"><br><br> <button type="button" onclick="deleteTechSkill(${index})">Delete Technical Skill</button><br><br> `; container.appendChild(fieldset); // 实时监听输入框变化,更新本地存储 const skillNameInput = fieldset.querySelector(`#skillName${index + 1}`); const expertiseInput = fieldset.querySelector(`#expertise${index + 1}`); const yearOfExpInput = fieldset.querySelector(`#yearOfExp${index + 1}`); skillNameInput.addEventListener('input', () => updateTechSkill(index, 'skill_name', skillNameInput.value)); expertiseInput.addEventListener('input', () => updateTechSkill(index, 'expertise', expertiseInput.value)); yearOfExpInput.addEventListener('input', () => updateTechSkill(index, 'year_of_exp', yearOfExpInput.value)); }); } // 实时更新单个技术技能数据到本地存储 function updateTechSkill(index, key, value) { const resumeData = JSON.parse(localStorage.getItem('resumeData')); resumeData.techskill[index][key] = value; localStorage.setItem('resumeData', JSON.stringify(resumeData)); }
添加技术技能函数
function addTechSkill() { const resumeData = JSON.parse(localStorage.getItem('resumeData')); // 添加空技能项 resumeData.techskill.push({ skill_name: "", expertise: "", year_of_exp: "" }); // 更新本地存储并重新渲染 localStorage.setItem('resumeData', JSON.stringify(resumeData)); renderTechSkills(); }
删除技术技能函数
function deleteTechSkill(index) { const resumeData = JSON.parse(localStorage.getItem('resumeData')); // 删除对应索引的技能项 resumeData.techskill.splice(index, 1); // 更新本地存储并重新渲染 localStorage.setItem('resumeData', JSON.stringify(resumeData)); renderTechSkills(); }
最终提交至后端函数(用户完成编辑后调用)
function submitResume() { const resumeData = localStorage.getItem('resumeData'); $.ajax({ url: '/app/submit-resume', type: 'POST', data: resumeData, contentType: 'application/json', headers: { 'X-CSRFToken': '{{ csrf_token }}' }, success: function() { alert('简历提交成功'); // 可选:提交后清空本地存储 localStorage.removeItem('resumeData'); }, error: function() { alert('提交失败,请重试'); } }); }
注意事项
- 数据安全传递:使用Django的
json_script过滤器传递初始数据,避免直接嵌入JSON带来的XSS风险 - 模块复用:教育经历、工作经验等模块可完全复用上述逻辑,仅需修改渲染函数中的数据字段名
- 本地存储限制:
localStorage约有5MB容量限制,简历类数据完全够用,超大数据量需另行处理 - 状态保留:
localStorage数据会在用户关闭页面后保留,若需每次打开重置为初始数据,可删除初始化时的本地存储判断逻辑
内容的提问来源于stack exchange,提问作者rishabh baradia
相关产品推荐
相关产品推荐

