如何提交Django表单且不丢失已渲染的HTML内容?
问题:Django提交表单页面重载丢失数据,如何无重载调用视图?
我是Django框架新手,正在开发一个包含3个HTML表单的小项目。预期流程为:先在「Input String」字段提交文本,再提交该文本的子串来增加分数。但提交子串时页面会重载,重置已渲染的HTML,导致丢失原输入的主字符串。点击「Submit Stuart」提交子串表单时,页面跳转到http://127.0.0.1:8000/someapp/consonant_submit,丢失原页面http://127.0.0.1:8000/someapp的HTML数据,想知道如何调用Django视图函数且不触发页面重载。
现有代码
HTML表单代码
<div style="padding: 20px;"> <h1>Words Starting with consonants</h1> <form id="form2" action="consonant_submit/" method="post"> {% csrf_token %} <label for="Stuart">Stuart Text:</label> <input type="text" id="stuart" name="stuart"> <br> <label for="2">Stuart Score:</label> <input type="text" id="score1" name="score1"> <br> <input type="submit" value="Submit stuart"> </form> </div> <div style="padding: 20px;"> <h1>Words Starting with consonants</h1> <form id="form3" action="vowel_submit/" method="post"> {% csrf_token %} <label for="kevin">Kevin Text:</label> <input type="text" id="kevin" name="kevin"> <br> <label for="2">Kevin Score:</label> <input type="text" id="score2" name="score2"> <br> <input type="submit" value="Submit kevin"> </form> </div>
urls.py代码
from django.urls import path from . import views urlpatterns = [ path("",views.index,name="index"), path('consonant_submit/', views.consonant_submit, name='consonant_submit'), path('vowel_submit/', views.vowel_submit, name='vowel_submit'), ]
views.py代码
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): res = render(request,'minion_game.html') return res def consonant_submit(request): if request.method == 'POST': input1 = request.POST.get('stuart') # Process the stuart data as needed res = render(request,'minion_game.html') return res else: return HttpResponse('Invalid request method') def vowel_submit(request): if request.method == 'POST': input2 = request.POST.get('kevin') # Process the kevin data as needed res = render(request,'minion_game.html') return res else: return HttpResponse('Invalid request method')
解决方案:用AJAX异步提交表单
核心是通过JavaScript的Fetch API异步发送表单数据,不触发页面跳转,同时保留页面原有内容。
1. 修改视图函数返回JSON响应
原来的视图提交后重新渲染页面,现在改为返回处理后的结果(比如计算后的分数),用JSON格式传递数据:
from django.shortcuts import render from django.http import JsonResponse def index(request): return render(request,'minion_game.html') def consonant_submit(request): if request.method == 'POST': input1 = request.POST.get('stuart') # 这里替换成你的实际分数计算逻辑 score = len(input1) # 示例:按子串长度算分 return JsonResponse({'status': 'success', 'score': score}) else: return JsonResponse({'status': 'error', 'message': '无效请求方法'}, status=400) def vowel_submit(request): if request.method == 'POST': input2 = request.POST.get('kevin') score = len(input2) # 示例计算逻辑 return JsonResponse({'status': 'success', 'score': score}) else: return JsonResponse({'status': 'error', 'message': '无效请求方法'}, status=400)
2. 修改HTML表单,添加JS异步提交逻辑
给表单添加提交事件监听,阻止默认跳转行为,用Fetch发送请求并更新页面内容:
<div style="padding: 20px;"> <h1>Words Starting with consonants</h1> <form id="form2" action="consonant_submit/" method="post"> {% csrf_token %} <label for="Stuart">Stuart Text:</label> <input type="text" id="stuart" name="stuart"> <br> <label for="score1">Stuart Score:</label> <input type="text" id="score1" name="score1" readonly> <br> <input type="submit" value="Submit stuart"> </form> </div> <div style="padding: 20px;"> <h1>Words Starting with vowels</h1> <form id="form3" action="vowel_submit/" method="post"> {% csrf_token %} <label for="kevin">Kevin Text:</label> <input type="text" id="kevin" name="kevin"> <br> <label for="score2">Kevin Score:</label> <input type="text" id="score2" name="score2" readonly> <br> <input type="submit" value="Submit kevin"> </form> </div> <script> // 获取Django的CSRF令牌,POST请求必须验证 const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; // 处理Stuart表单提交 document.getElementById('form2').addEventListener('submit', function(e) { e.preventDefault(); // 阻止默认页面跳转 const formData = new FormData(this); fetch(this.action, { method: 'POST', headers: { 'X-CSRFToken': csrftoken, }, body: formData }) .then(response => response.json()) .then(data => { if (data.status === 'success') { // 更新页面上的分数显示 document.getElementById('score1').value = data.score; } else { alert(data.message); } }) .catch(() => alert('提交失败,请重试')); }); // 处理Kevin表单提交 document.getElementById('form3').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); fetch(this.action, { method: 'POST', headers: { 'X-CSRFToken': csrftoken, }, body: formData }) .then(response => response.json()) .then(data => { if (data.status === 'success') { document.getElementById('score2').value = data.score; } else { alert(data.message); } }) .catch(() => alert('提交失败,请重试')); }); </script>
3. 保留主字符串的小技巧
如果需要持久化用户输入的主字符串,可以用以下两种方式:
- 隐藏输入框:主字符串提交后,把值存入页面的隐藏输入框,后续提交子串时可以一起传递:
<input type="hidden" id="main_string" name="main_string" value="{{ main_string }}"> - localStorage存储:用JavaScript把主字符串存在浏览器本地存储,需要时取出:
// 主字符串提交时保存 localStorage.setItem('mainString', document.getElementById('main_input').value); // 后续需要时读取 const mainStr = localStorage.getItem('mainString');
内容的提问来源于stack exchange,提问作者AnkMan
相关产品推荐
相关产品推荐

