【问题标题】:How to deserialize a serialized queryset in Django?如何反序列化 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?或者还有其他方法可以实现吗?

【问题讨论】:

    标签: python django django-views django-serializer django-sessions


    【解决方案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 Djangopk 属性是使用主键的便捷方式。

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

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

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

    【讨论】:

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