腌制 queryset.query 对象时可怕的“不是同一对象错误”

问题描述 投票:0回答:4

我有一个查询集,我需要延迟腌制,但我遇到了一些严重的麻烦。

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

奇怪的是(或者也许不是那么奇怪),只有当我从另一个方法或视图调用

cPickle
时,我才会收到该错误,但当我从命令行调用它时,不会收到该错误。

在阅读 PicklingError: Can't pickle : it's not the same object asdecimal.DecimalDjango 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
,但这并没有解决问题。

编辑2:我在上面显示的错误中有一个拼写错误——它是

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是models下的模块之一。我的模型中有一个

__ini__.py
,其中包含以下行:

from myfile import *

我想知道这是否会导致我的问题。有什么方法可以改变我的

init
来保护自己免受这种情况的影响?还有其他测试可以尝试吗?

EDIT3: 这是我的用例的更多背景信息:我有一个名为

Context
的模型,我用它来使用
mymodel
的实例填充 UI 元素。用户可以在 UI 端添加/删除/操作对象,更改它们的上下文,并且当它们返回时,它们可以保留它们的更改,因为上下文序列化了所有内容。上下文对于用户可以操作对象的不同类型的过滤器/方式有一个通用外键,所有这些都必须实现上下文用来确定它应该显示的内容的一些方法。其中一个过滤器采用可传入的查询集并显示该查询集中的所有对象。这提供了一种传递在其他地方生成的任意查询集并将它们显示在 UI 元素中的方法。使用 Context 的模型是分层的(为此使用 mptt),每次用户单击时,UI 元素都会发出获取子元素的请求,然后我们可以获取子元素并根据是否显示来确定它们是否应该显示它们包含在上下文中。希望有帮助!

编辑4:我能够转储一个空查询集,但是一旦我添加任何有价值的内容,它就会失败。

EDIT4:我使用的是 Django 1.2.3

python django serialization pickle
4个回答
7
投票

这可能不是每个人的情况,但我正在使用 Ipython 笔记本,并且在酸洗我自己的类时遇到类似的问题。 问题原来是由重新加载调用引起的

from dir.my_module import my_class    
reload(dir.my_module)

删除重新加载调用,然后重新运行导入和创建该对象实例的单元格,然后允许对其进行腌制。


1
投票

不太优雅,但也许可行: 将

myfile
模块的目录添加到
os.sys.path
,并在使用
import myfile
的每个模块中仅使用
myfile
。 (删除项目中任意位置的所有
from segment.segmentengine.models.segment import


0
投票

根据这个doc,pickle QuerySet 应该不是问题。因此,问题应该来自其他地方。

既然你提到了:

EDIT2:我在上面显示的错误中出现了拼写错误——它抱怨的是 models.QuerySet,而不是 models.mymodel.QuerySet。这里还有另一个细微差别,那就是我的模型文件被分解为多个模块,所以错误实际上是:

  1. 您提供的第二条错误消息看起来与上一条相同,是您的意思吗?
  2. 您提供的错误消息看起来很奇怪。由于您正在酸洗“queryset.query”,因此错误应该与 django.db.models.sql.Query 类而不是 QuerySet 类相关。

某些模块或类可能具有相同的名称。它们会互相覆盖然后导致此类问题。为了让事情变得更简单,我建议您使用“import ooo.xxx”而不是“from ooo import *”。


0
投票

你也可以尝试

import ooo.xxx as othername
© www.soinside.com 2019 - 2024. All rights reserved.