【发布时间】:2011-10-06 22:19:45
【问题描述】:
我有一个查询集,我需要懒惰地腌制,我遇到了一些严重的问题。 cPickle.dumps(queryset.query) 抛出以下错误:
Can't pickle <class 'myproject.myapp.models.myfile.QuerySet'>: it's not the same object as myproject.myapp.models.myfile.QuerySet
奇怪的是(或者可能不那么奇怪),当我从另一个方法或视图调用cPcikle 时,我只会收到该错误,但从命令行调用它时不会。
我看了PicklingError: Can't pickle <class 'decimal.Decimal'>: it's not the same object as decimal.Decimal和Django mod_wsgi PicklingError while saving object之后做了下面的方法:
def dump_queryset(queryset, model):
from segment.segmentengine.models.segment import QuerySet
memo = {}
new_queryset = deepcopy(queryset, memo)
memo = {}
new_query = deepcopy(new_queryset.query, memo)
queryset = QuerySet(model=model, query=new_query)
return cPickle.dumps(queryset.query)
如您所见,我变得非常绝望——这种方法仍然会产生同样的错误。这个问题有已知的、非hacky的解决方案吗?
编辑:尝试使用在 django 开发服务器上运行的--noreload,但无济于事。
EDIT2: 我在上面显示的错误中有一个错字——它抱怨的是models.QuerySet,而不是models.mymodel.QuerySet。这里还有另一个细微差别,即我的模型文件被分解为多个模块,因此错误实际上是:
Can't pickle <class 'myproject.myapp.models.myfile.QuerySet'>: it's not the same object as myproject.myapp.models.myfile.QuerySet
其中 myfile 是模型下的模块之一。我在具有以下行的模型中有一个 __ini__.py:
from myfile import *
我想知道这是否导致了我的问题。有什么方法可以改变我的init 来保护自己免受这种情况的影响吗?还有其他测试可以尝试吗?
EDIT3: 下面是我的用例的更多背景信息:我有一个名为 Context 的模型,我用它来填充带有 mymodel 实例的 UI 元素。用户可以在 UI 端添加/删除/操作对象,更改它们的上下文,当它们返回时,他们可以保留它们的更改,因为上下文序列化了一切。上下文对于不同类型的过滤器/用户可以操作对象的方式具有通用外键,所有这些都必须实现上下文用来确定应该显示什么的一些方法。一个这样的过滤器采用可以传入的查询集并显示该查询集中的所有对象。这提供了一种传递在其他地方生成的任意查询集并将它们显示在 UI 元素中的方法。使用 Context 的模型是分层的(为此使用 mptt),并且每次用户点击时 UI 元素都会请求获取子项,然后我们可以获取子项并根据是否显示它们来确定它们它们包含在上下文中。希望对您有所帮助!
EDIT4:我可以转储一个空的查询集,但只要我添加任何有价值的东西,它就会失败。
EDIT4:我在 Django 1.2.3
【问题讨论】:
-
您直接调用 magic_methods。您应该导入副本并使用 copy.deepcopy 功能。
-
但这并不能解决您的问题。您可以回溯 Django(重新)加载模块的方式和时间。并尝试在顶层以预定义的方式加载它们。 django 开发服务器做了各种方便的自动重新加载,现在对你没有帮助。尝试使用--noreload 运行它。
-
如果您能详细说明一下腌制查询集的目的是什么,也许会很有用?
-
根据这篇文章,pickle一个查询集应该没问题。 docs.djangoproject.com/en/dev/ref/models/querysets 我猜这个问题可能在其他地方有所贡献。
-
好吧,也许您可以验证两件事: 1. 如果您不分配另一个查询(查询为空),酸洗是否有效? 2.尝试像
from segment.segmentengine.models import segment那样做导入,然后做queryset = segment.QuerySet(model=model, query=new_query)
标签: python django serialization pickle