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

Posted

技术标签:

【中文标题】如何反序列化 Django 中的序列化查询集?【英文标题】:How to deserialize a serialized queryset in Django? 【发布时间】:2021-12-27 13:45:55 【问题描述】:

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?或者还有其他方法可以实现吗?

【问题讨论】:

【参考方案1】:

你只需要使用反向方法,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)

【讨论】:

比如,rp=request.session['report'],那么,rp_qs=serializers.deserialize("queryset", rp)?我用什么代替第一个参数? 我只是编辑答案以包含一个示例,说明实现您想要的可能方式【参考方案2】:

该问题专门询问有关获取QuerySet 的问题,因此值得注意的是调用serializers.deserialize(根据@cabesuon 的回答)不会这样做 - 它返回一个生成DeserializedObject 的生成器。如果这对您的用例来说还不够好,您可能需要重建一个 QuerySet

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

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

Django documentation about serialization 备注:

Django 对象本身可以被检查为deserialized_object.object

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

本质上,我们对函数式编程map() 构造所做的工作是将我们返回的DeseralizedObject 实例生成器转换为一系列主键。 lambda 的全部目的是访问我们想要的属性(它等同于operator.itemgetter("object.pk"),但不需要导入operator 模块,而且更明显)。之后,我们将该结果序列传递给 .filter(),以查找以您序列化的 QuerySet 结尾的 IpdReport 实例。

如果您想了解更多关于 python 函数式编程的信息,您可能需要查看HOWTO on the topic。

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

【讨论】:

谢谢。有用!我是初学者,这对我来说是新的学习。为此非常感谢。我只有一个疑问。您能否更慷慨地解释一下 lambda 函数“o.object.pk”中的那个表达式。我在哪里可以了解有关此表达式的更多信息?并再次感谢您的回答。 :) @noob87 添加了一个编辑,希望能提供更多上下文并指向一些额外的资源。如果您还有其他问题,请告诉我。 非常感谢。我一定会研究它并尝试学习得更好。干杯! :)

以上是关于如何反序列化 Django 中的序列化查询集?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中序列化模型实例?

如何从序列化器字段订购 django rest 框架查询集?

序列化/反序列化大型数据集

测试Hessian反序反序列化 客户端少字段和多字段时能否成功

C#反序列化Json字符串

如何反序列化 .net 核心中的 json 数据集