如何为Django HTML网页实现滚动锁定 避免表单提交后返回顶部
解决方案
问题本质是传统表单提交会触发全页面重定向/刷新,浏览器默认会重置滚动位置到顶部,以下提供两种可直接落地的方案:
方案1:AJAX异步提交(推荐,无刷新体验最优)
无需页面跳转,提交后原地更新状态,完全不会改变滚动位置,最适合快速录入数据的场景。
步骤1:修改HTML模板
给每个表单添加标识,新增JS提交逻辑拦截默认提交行为:
<!-- 给form新增类、数据属性和唯一ID --> <form class="form-group mt-4 avonlea-form" method="post" data-unit="{{unit_number.data.value}}" id="unit-{{unit_number.data.value}}" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} > <!-- 原有表单内容保持不变 --> </form> <!-- 页面底部新增JS逻辑 --> <script> document.querySelectorAll('.avonlea-form').forEach(form => { form.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(form); const submitBtn = form.querySelector('button[type="submit"]'); try { const res = await fetch(window.location.href, { method: 'POST', body: formData, headers: { 'X-CSRFToken': form.querySelector('[name=csrfmiddlewaretoken]').value } }); const result = await res.json(); if(result.status === 'success') { // 提交成功后把表单置灰、按钮禁用,和已提交样式保持一致 form.style.backgroundColor = 'rgb(231, 224, 224)'; submitBtn.disabled = true; } else { alert('提交失败:' + result.msg); } } catch(err) { alert('请求异常,请重试'); } }) }) </script>
步骤2:修改Views.py的post逻辑
兼容AJAX请求,返回JSON响应:
from django.http import JsonResponse from django.urls import reverse def post(self,request): created_nums= AvonleaClass.objects.all().values_list('unitNumber', flat=True) # 注意要加request.FILES,否则表单的图片上传功能会失效 form = AvonleaForm(request.POST, request.FILES) if form.is_valid(): form.save() messages.success(request , '创建成功') # 判断是否为AJAX请求,是则返回JSON if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' or request.accepts('application/json'): return JsonResponse({'status':'success', 'msg':'保存成功'}) return redirect('Avonlea') else: if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' or request.accepts('application/json'): return JsonResponse({'status':'error', 'msg':form.errors.as_text()}) # 原代码传递created_nums时漏了参数名引号,已修正 return render(request, 'meter_readings/avonlea.html', {'form': form , 'created_nums':created_nums })
注意:原代码中messages.success写在redirect之后,属于不可达代码,以上代码已经调整了执行顺序。
方案2:锚点跳转(改造成本最低,无需JS)
提交后页面仍会刷新,但会自动定位到刚刚提交的表单位置,适合不想改动前端逻辑的场景。
步骤1:给表单添加锚点ID
给每个form标签添加唯一ID作为锚点:
<form id="unit-{{unit_number.data.value}}" class="form-group mt-4" method="post" {% if unit_number.data.value in created_nums %} style="background-color: rgb(231, 224, 224); " {% endif %} >
步骤2:修改重定向逻辑,携带锚点
def post(self,request): created_nums= AvonleaClass.objects.all().values_list('unitNumber', flat=True) form = AvonleaForm(request.POST, request.FILES) if form.is_valid(): saved_obj = form.save() messages.success(request , '创建成功') # 重定向时带上提交成功的表单锚点 return redirect(f'{reverse("Avonlea")}#unit-{saved_obj.unitNumber}') else: return render(request, 'meter_readings/avonlea.html', {'form': form , 'created_nums':created_nums })
内容的提问来源于stack exchange,提问作者KyleStranger
相关产品推荐
相关产品推荐

