Django重定向后模板变量未更新 如何无刷新修改parsing值
问题核心原因
两个逻辑错误导致你遇到现在的现象:
- AJAX请求的重定向不会触发页面更新:AJAX是浏览器后台发起的异步请求,就算后端返回302重定向,也只会让AJAX对象在后台默默请求重定向后的地址,整个过程不会替换当前已经加载完成的页面DOM,你写在模板里的
{{ parsing }}是页面首次加载时就渲染成固定文本的,后台拿到的新页面内容不会自动替换到当前页面上。 - 状态没有持久化:你每次在视图里写
frontendTracker = FrontendTracker()都是创建一个全新的实例,视图函数返回后这个实例就会被内存回收,你在POST接口里给这个实例设置的parsing=True根本不会留存到下一次请求,就算手动刷新页面,读到的也是新实例的默认值。
无刷新实现方案
全程不需要刷新页面,也不会中断你页面上已经在运行的其他JS逻辑,分三步修改:
1. 改造后端接口,用session持久化用户状态,给AJAX返回JSON
不要用请求级别的临时对象存状态,直接把用户的解析状态存在Django自带的session里,同一个用户的所有请求都能共享这个状态,同时AJAX接口不要返回重定向,直接返回JSON格式的状态数据:
from django.http import JsonResponse from django.shortcuts import redirect from django.views.generic import TemplateView def initialize_before_parsing(request): if request.method == 'POST': # 状态写入当前用户session,跨请求留存 request.session['parsing'] = True request.session['progress'] = 0 request.session['showAnnotationButton'] = False # 直接给AJAX返回状态JSON,不需要重定向 return JsonResponse({ "code": 0, "data": { "parsing": True, "progress": 0 } }) return redirect("index") class IndexView(TemplateView): template_name = 'index.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 首次加载页面时从session读状态,给默认兜底值 context["showAnnotation"] = self.request.session.get('showAnnotationButton', False) context["parsing"] = self.request.session.get('parsing', False) context["progress"] = self.request.session.get('progress', 0) return context
路由配置不需要改动。
2. 改造前端AJAX逻辑,拿到状态后直接更新DOM
给AJAX加success回调,请求成功后直接操作DOM修改按钮状态,不需要整页刷新:
$('#parseButton').click(function () { const $parseBtn = $(this); $.ajax({ type: 'POST', url: 'initialize_parsing/', headers:{"X-CSRFToken": $.cookie("csrftoken")}, data: {}, success: function(res) { if (res.code === 0) { // 直接给按钮加禁用属性,无需等待模板重新渲染 $parseBtn.attr('disabled', true); // 其他需要同步的状态(比如进度条)也直接在这里改DOM即可 // 例:$('#progress-bar').css('width', `${res.data.progress}%`); } } }); });
你原来的模板部分不需要改动,首次进入页面时的按钮禁用状态还是由模板变量控制,点击后的状态由AJAX回调直接更新DOM,两边逻辑不冲突。
3. 后续扩展提示
如果需要实时同步解析进度,只要再加一个简单的进度查询接口,从session里读取最新的progress值返回JSON,前端用定时器每隔1-2秒请求一次这个接口,拿到进度后直接更新进度条DOM即可;解析完成后把session里的parsing设为False,前端拿到状态后把按钮的disabled属性移除就行,全程不需要刷新页面。
注意:不要用全局Python变量存多用户共享的状态,多线程/多进程部署时会出现用户状态串流的问题,用session存每个用户自己的状态是最简便且安全的方案,如果需要跨服务共享状态再考虑换用缓存存储。
内容的提问来源于stack exchange,提问作者Luka
相关产品推荐
相关产品推荐

