Django同一视图处理多提交请求时无需返回未修改表单的方法?
解决方案
你遇到的表单重置问题核心原因是两个按钮分属独立的<form>标签,点击click_button时只会提交当前表单的内容(仅csrf token),不会携带第一个表单的用户输入数据,以下是三种可落地的方案,按优先度排序:
方案1:合并表单(最优解,改动最小)
将两个提交按钮放到同一个表单内部,这样无论点击哪个按钮,都会自动携带全部表单字段的输入值,不需要额外存储逻辑:
- 修改
home.html结构:
<body> {% load bootstrap4 %} <form action="" method="POST" novalidate> {% csrf_token %} {% bootstrap_form form %} <!-- 原Django表单提交按钮(如果有也放在该表单内) --> <button class="btn btn-success" name="form_submit" type="submit">提交表单</button> <!-- 把自定义操作按钮移到当前表单内部 --> <button class="btn btn-primary" name="click_button" type="submit">Grafik</button> </form> </body>
- 修改
views.py逻辑:
def get_post_from_submit(request): form = form_book() if request.method == 'POST': # 统一用POST数据初始化form,保留用户所有输入 form = form_book(request.POST) if "form_submit" in request.POST: # 原表单提交业务逻辑 if form.is_valid(): # 你的业务代码 pass if "click_button" in request.POST: # 自定义按钮的业务逻辑 pass return render(request, 'home.html',{"form": form})
方案2:Session存储表单数据(适用于必须拆分表单的场景)
如果业务要求两个按钮必须分属不同表单,可以把用户之前提交的合法表单数据存在Session中,点击自定义按钮时从Session取数据初始化form,避免重置:
修改views.py逻辑:
def get_post_from_submit(request): # 初始化时优先从Session取已保存的表单数据 form_data = request.session.get('book_form_data', None) form = form_book(form_data) if form_data else form_book() if request.method == 'POST': if "book_field" in request.POST: form = form_book(request.POST) if form.is_valid(): # 执行业务逻辑后保存数据到Session request.session['book_form_data'] = request.POST.dict() if "click_button" in request.POST: # 执行自定义按钮的业务逻辑,此时form已用Session数据初始化,不会为空 pass return render(request, 'home.html',{"form": form})
如果需要清空表单可以在对应业务逻辑后执行del request.session['book_form_data']
方案3:AJAX提交(完全不需要返回form对象)
如果点击click_button不需要刷新整个页面,直接用AJAX提交请求即可,页面不会重载,用户输入的表单内容会自动保留,后端不需要返回form对象,也不需要渲染整个模板:
- 给按钮加id方便绑定事件:
<button id="grafik_btn" class="btn btn-primary" name="click_button" type="button">Grafik</button>
- 加JS提交逻辑:
document.querySelector('#grafik_btn').addEventListener('click', function() { fetch('', { method: 'POST', headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'click_button=1' }).then(res => res.json()).then(data => { // 处理返回的业务数据,比如渲染图表 }) })
- 后端逻辑调整:
from django.http import JsonResponse def get_post_from_submit(request): if request.method == 'POST': if "book_field" in request.POST: form = form_book(request.POST) # 原表单提交逻辑不变 return render(request, 'home.html',{"form": form}) if "click_button" in request.POST: # 执行业务逻辑,直接返回JSON,不需要构造form对象 return JsonResponse({"status": "success", "data": your_biz_data}) # GET请求逻辑不变 return render(request, 'home.html',{"form": form_book()})
内容的提问来源于stack exchange,提问作者Squeezie
相关产品推荐
相关产品推荐

