如何反序列化 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 rest 框架查询集?