Django中如何反序列化已存入session的序列化QuerySet?
方案1:将序列化JSON转为模型实例集合(不推荐)
注意:已经序列化后的JSON数据无法转回原生QuerySet对象,QuerySet是Django ORM中绑定数据库查询的懒加载代理对象,序列化后得到的是数据快照,仅能还原为模型实例的集合,足够满足导出Excel的遍历需求。
操作代码如下:
from django.core import serializers def export_excel_view(request): rp = request.session.get('report') if not rp: # 自行补充无数据时的异常处理逻辑 ... # 直接反序列化json字符串得到模型实例列表 ipd_instances = [item.object for item in serializers.deserialize("json", rp)] # 后续遍历ipd_instances写入Excel即可
该方案存在以下明显问题:
- Django默认session存储有大小上限,数据量较大时会存储失败
- 序列化、反序列化过程有额外性能损耗,数据量越大损耗越明显
- session中存储的是数据快照,若期间数据库对应记录有更新,导出的是过期旧数据
方案2:更合理的实现方案(推荐)
不要在session中存储整个结果集,改为存储筛选参数,导出时重新查询数据库得到原生QuerySet,完全避免上述问题。
首先修改原ipd_report_view逻辑:
def ipd_report_view(request): report=IpdReport.objects.all() myFilter=IpdFilters(request.POST, queryset=report) report=myFilter.qs # 存储筛选参数,而非序列化后的结果集 request.session['ipd_filter_params'] = request.POST.dict() total1=report.aggregate(Sum('realization__amount_received')) total2=report.aggregate(Sum('realization__deficit_or_surplus_amount')) context={'report': report, 'total1':total1, 'total2':total2, 'myFilter':myFilter} return render(request, 'account/ipdreport.html', context)
导出视图逻辑:
def export_excel_view(request): filter_params = request.session.get('ipd_filter_params', {}) # 用存储的筛选参数重新查询得到原生QuerySet report_qs = IpdFilters(filter_params, queryset=IpdReport.objects.all()).qs # 直接用report_qs实现Excel导出逻辑即可 ...
该方案优势:
- 无需处理序列化、反序列化逻辑,代码更易维护
- 仅存储筛选参数,session存储占用极小,不受数据量大小限制
- 导出时查询最新数据库数据,不会出现数据不一致问题
- 得到原生
QuerySet,支持所有ORM操作,灵活度更高
内容的提问来源于stack exchange,提问作者noob87
相关产品推荐
相关产品推荐

