如何反序列化 Django 中的序列化查询集?

How to deserialize a serialized queryset in Django?

views.py

def ipd_report_view(request):
    report=IpdReport.objects.all()
    myFilter=IpdFilters(request.POST, queryset=report)
    report=myFilter.qs
    total1=report.aggregate(Sum('realization__amount_received'))
    total2=report.aggregate(Sum('realization__deficit_or_surplus_amount'))
    rp=serializers.serialize('json', report)
    request.session['report']=rp
    context={'report': report, 'total1':total1, 'total2':total2, 'myFilter':myFilter}
    return render(request, 'account/ipdreport.html', context)

在另一个 view 函数中,我必须使用 session 中的数据才能使函数将数据导出到 excel 文件。

我做了 rp=request.session['report'],但是这个 object 是一个 string 对象,那么我该如何将它转换回 queryset?或者还有其他方法可以实现吗?

你只需要使用反向方法,deserialize,

Django Docs - Serialization, deserializing-data

在你的情况下,它会是这样的,

// serializers.deserialize returns an iterator,
// but we know is just one element
obj = list(serializers.deserialize("json", request.session['report']))[0]
// obj is a DeserializedObject not the instance of the model
// to inspect the element just use the object property
rp = IpdReport.objects.get(pk=obj.object.pk)

这个问题特别询问了关于获得 QuerySet 的问题,因此值得注意的是调用 serializers.deserialize(根据@cabesuon 的回答)不会那样做 - 它 returns 生成器产生 DeserializedObject。如果这对您的用例来说不够好,您可能需要重建一个 QuerySet:

IpdReport.objects.filter(
    pk__in=map(
        lambda o: o.object.pk,
        serializers.deserialize("json", request.session["report"]),
    )
)

编辑:详细说明这里发生的事情:

Django documentation about serialization 备注:

The Django object itself can be inspected as deserialized_object.object.

此外,该 Django 对象的 pk 属性 is provided by Django 作为使用主键的便捷方式。

本质上,我们使用函数式编程 map() 构造所做的是将我们返回的 DeseralizedObject 实例生成器转换为一系列主键。 lambda 的全部目的是访问我们想要的属性(它等同于 operator.itemgetter("object.pk") 但不需要导入 operator 模块并且更直接明显)。之后,我们将生成的序列传递给 .filter() 以查找 IpdReport 个实例,这些实例最终出现在您序列化的 QuerySet 中。

如果您想阅读 python 中有关函数式编程的更多信息,您可能需要查看 HOWTO on the topic

还值得注意的是,整个方法有一个潜在的重大缺点 - 数据库的状态可能会在序列化和反序列化之间改变 - 这可能会导致一些不一致(得到的结果不再匹配以前应用的过滤器,或者相反- 没有得到应该与过滤器匹配但以前没有的结果)。因此,您可能需要查看 serializing QuerySet.query.