如何在Django中从一个视图向另一个视图传递QuerySet?Session方案尝试无效
在Django中跨视图传递元组列表的解决方案
我之前也碰到过类似的情况,你说Session方案没生效大概率是因为直接存了模型实例——Django的Session要求存储的内容必须是可序列化的,而模型实例本身没办法直接序列化,所以导致数据没存进去。下面给你几个靠谱的解决方案,亲测有效:
方法1:修正Session的用法(最常用)
核心思路是把元组里的模型实例转换成主键(ID)存储,到目标视图里再根据ID查询回完整的模型对象。具体代码如下:
# views.py from django.shortcuts import redirect from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404 @login_required def view1(request): # 先把模型实例转成ID,再组成元组存入列表 job_details = [] # 假设这里是你生成job、recruiter、salary的逻辑 job_details.append((job.id, recruiter.id, salary)) # 存入Session request.session['job_details'] = job_details # 跳转到view2 return redirect('view2') @login_required def view2(request): # 从Session取出数据,默认空列表避免报错 raw_details = request.session.get('job_details', []) # 还原成模型实例 job_details = [] for job_id, recruiter_id, salary in raw_details: # 用get_object_or_404处理查询不存在的情况 job = get_object_or_404(Job, id=job_id) recruiter = get_object_or_404(Recruiter, id=recruiter_id) job_details.append((job, recruiter, salary)) # 这里就可以用job_details做你要的操作了 # 用完可以删除Session里的缓存,避免占用空间 del request.session['job_details'] # 后续逻辑...
方法2:使用缓存传递(适合数据量大的情况)
如果你的元组列表数据比较多,Session可能会有存储限制,这时候用Django的缓存更合适。我们可以生成一个唯一的缓存键,把数据存在缓存里,再把键传递给目标视图:
# views.py from django.core.cache import cache import uuid from django.shortcuts import redirect, get_object_or_404 def view1(request): job_details = [] job_details.append((job.id, recruiter.id, salary)) # 生成唯一缓存键 cache_key = str(uuid.uuid4()) # 存入缓存,设置过期时间(比如5分钟,避免占用缓存) cache.set(cache_key, job_details, timeout=300) # 把缓存键作为URL参数传递给view2 return redirect('view2', cache_key=cache_key) # urls.py里要对应配置view2的URL,比如: # path('view2/<str:cache_key>/', views.view2, name='view2') def view2(request, cache_key): # 从缓存取出数据 raw_details = cache.get(cache_key) job_details = [] if raw_details: # 还原模型实例 for job_id, recruiter_id, salary in raw_details: job = get_object_or_404(Job, id=job_id) recruiter = get_object_or_404(Recruiter, id=recruiter_id) job_details.append((job, recruiter, salary)) # 用完删除缓存,节省空间 cache.delete(cache_key) else: # 处理数据过期或不存在的情况 pass # 后续逻辑...
方法3:表单POST传递(适合小数据量)
如果是通过表单提交跳转到view2,也可以把数据放在隐藏字段里传递。不过这种方法只适合数据量小的情况,不然会显得很臃肿:
# view1里返回带有隐藏字段的表单 def view1(request): job_details = [] job_details.append((job.id, recruiter.id, salary)) # 把数据序列化成JSON字符串 import json data_json = json.dumps(job_details) return render(request, 'transfer_form.html', {'data_json': data_json})
然后在模板transfer_form.html里:
<form method="post" action="{% url 'view2' %}"> {% csrf_token %} <input type="hidden" name="job_details" value="{{ data_json }}"> <button type="submit">跳转到view2</button> </form>
最后在view2里解析:
def view2(request): if request.method == 'POST': import json raw_details = json.loads(request.POST.get('job_details', '[]')) job_details = [] for job_id, recruiter_id, salary in raw_details: job = get_object_or_404(Job, id=job_id) recruiter = get_object_or_404(Recruiter, id=recruiter_id) job_details.append((job, recruiter, salary)) # 后续逻辑...
重要提醒
- 绝对不要用全局变量来存储
job_details!Django是多用户的Web框架,全局变量会被所有用户共享,导致数据混乱。 - 不管用哪种方法,都要处理模型查询失败的情况,比如用
get_object_or_404替代get,避免抛出未处理的异常。
内容的提问来源于stack exchange,提问作者Alpha
相关产品推荐
相关产品推荐

