如何在Django类POST方法中保存变量,解决表单选值后刷新数据失效问题
解决Django类视图POST保存值后GET无法获取的问题
嘿,我一眼就看出问题所在了——Django的类视图每次请求都会创建一个全新的实例。你在POST方法里给self.case_account赋值,只对当前POST请求的那个视图实例有效;当你重定向到GET请求时,系统会生成一个新的MovementsListView实例,原来的self.case_account早就被销毁了,自然回到初始的None状态。
下面给你三种靠谱的解决方案,你可以根据业务场景挑选:
方案1:用Session存储值(推荐,适合敏感数据)
Session是Django用来在请求间保存用户数据的机制,非常适合这种跨请求传递值的场景:
class MovementsListView(TemplateView, CurrentURLMixin): allow_empty = True template_name = "movement_index.html" accounts = None info_account = None case_account = None def get(self, request, *args, **kwargs): # 从session中读取保存的case_account值 self.case_account = request.session.get('case_account') self.accounts = Account.objects.all() print(self.case_account) # 现在能拿到POST提交的值了 # 根据case_account过滤数据,无值时返回空查询集 if self.case_account: self.info_account = Account.objects.filter(account_code=self.case_account) else: self.info_account = Account.objects.none() return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["accounts"] = self.accounts context["info_account"] = self.info_account context["selected_case"] = self.case_account # 传回模板用于回显选中状态 return context def post(self, request, *args, **kwargs): self.case_account = request.POST["case_account"] print(self.case_account) # 将值存入session,实现跨请求保存 request.session['case_account'] = self.case_account return redirect("movement_index")
优点:数据不会暴露在URL中,适合敏感信息;用户刷新页面后值依然保留。
方案2:重定向时把参数放到URL中(适合非敏感数据)
如果case_account不是敏感数据,可以把它作为URL参数传递,让GET请求直接读取:
首先修改URL配置,新增带参数的路由:
# urls.py path('movements/<str:case_account>/', MovementsListView.as_view(), name='movement_index_with_param'), path('movements/', MovementsListView.as_view(), name='movement_index'),
然后修改视图逻辑:
class MovementsListView(TemplateView, CurrentURLMixin): # 其他属性保持不变 def get(self, request, *args, **kwargs): # 从URL的kwargs中获取参数,无值时为None self.case_account = kwargs.get('case_account') self.accounts = Account.objects.all() print(self.case_account) if self.case_account: self.info_account = Account.objects.filter(account_code=self.case_account) else: self.info_account = Account.objects.none() return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): case_account = request.POST["case_account"] print(case_account) # 重定向到带参数的路由 return redirect("movement_index_with_param", case_account=case_account)
优点:逻辑简单,用户可以分享带参数的URL,他人打开能看到相同的筛选结果;缺点:参数会显示在浏览器地址栏,不适合敏感数据。
方案3:改用GET请求提交表单(最简单的方案)
如果表单只是用于筛选数据、不涉及服务器数据修改,完全可以把表单的method改成GET,省去重定向的步骤:
首先修改模板中的表单:
<!-- movement_index.html --> <form method="get"> <select name="case_account"> <!-- 你的下拉选项 --> </select> <button type="submit">确认选择</button> </form>
然后修改视图:
class MovementsListView(TemplateView, CurrentURLMixin): # 其他属性保持不变 def get(self, request, *args, **kwargs): # 直接从GET参数中读取选中值,默认None self.case_account = request.GET.get('case_account') self.accounts = Account.objects.all() print(self.case_account) if self.case_account: self.info_account = Account.objects.filter(account_code=self.case_account) else: self.info_account = Account.objects.none() return super().get(request, *args, **kwargs) # 可以删除post方法,因为现在用GET提交表单
优点:代码量最少,逻辑最简洁;缺点:参数会显示在URL中,且表单提交会生成新的浏览器历史记录(用户点击后退会看到重复请求)。
你可以根据自己的业务需求选择最合适的方案,个人优先推荐方案1(Session),除非你需要支持URL分享或数据完全公开。
内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

