Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在执行之前将芹菜的Django Queryset序列化为JSON_Django_Celery_Django Queryset - Fatal编程技术网

在执行之前将芹菜的Django Queryset序列化为JSON

在执行之前将芹菜的Django Queryset序列化为JSON,django,celery,django-queryset,Django,Celery,Django Queryset,我从一个外部库获得了一个Queryset,由于Queryset是惰性的,我想在数据库中访问它并执行它之前将其序列化为JSON,因此它可以在异步芹菜任务中执行 我的问题是,有没有一种方法可以将Queryset的基本元素表示为JSON,这样我就不必使用Pickle了 我知道我可以使用queryset.query获得原始查询,但由于我必须在另一端执行原始查询,我不太喜欢这种想法 细节 这里的特定用例是评估任务中的查询集,以便将结果导出到文件并转储到服务器上以供以后访问 结果集可能非常大,因此作为标准请

我从一个外部库获得了一个Queryset,由于Queryset是惰性的,我想在数据库中访问它并执行它之前将其序列化为JSON,因此它可以在异步芹菜任务中执行

我的问题是,有没有一种方法可以将Queryset的基本元素表示为JSON,这样我就不必使用Pickle了

我知道我可以使用
queryset.query
获得原始查询,但由于我必须在另一端执行原始查询,我不太喜欢这种想法

细节 这里的特定用例是评估任务中的查询集,以便将结果导出到文件并转储到服务器上以供以后访问

结果集可能非常大,因此作为标准请求/响应周期的一部分进行导出通常会超时

该请求由Django管理员更改视图列表筛选器生成。我试着回顾一下列表过滤器代码,但它似乎只生成过滤器对象——不适合JSON序列化


我可以查看列表过滤器查询字符串并将所有键重新计算为Queryset过滤器,但许多过滤器都是
SimpleListFilter
类,它们也只返回过滤器对象,并且不会在URL中显示真正的Queryset过滤器。我需要为这些过滤器重新创建逻辑,以获得可以JSON序列化的kwarg样式的过滤器。

您不必序列化
QuerySet
就可以在芹菜任务中访问它。您可以使用Django模型并在任务本身中创建
QuerySet
。如果有某种创建
QuerySet
的特定方式,则可以将
QuerySet
创建代码放入公共函数或类中,并将此共享代码导入web应用程序代码和芹菜任务中

没有理由避免在芹菜任务中使用Django ORM。

Django 1.11和芹菜3.0的更新 可悲的是,这已经不起作用了。如果任何人在执行之前有任何关于如何正确序列化queryset或其各种筛选器和属性的信息,请告诉我

原始答案 事实证明,
my_queryset.query
是在执行查询集之前序列化查询集的正确且安全的方法

如果您只想在以后从数据库中pickle重新创建QuerySet所需的信息,请pickle QuerySet的query属性。然后,您可以使用以下代码重新创建原始QuerySet(不加载任何结果):

查询属性是不透明对象。它表示查询构造的内部结构,不是公共API的一部分。但是,按照此处所述对属性的内容进行pickle和unpickle是安全的(并且完全受支持的)

这涉及到使用pickle,但它当然也可以使用JSON序列化程序

# admin.py
...
    export_data.delay(queryset.query)
...

# tasks.py
@task(serializer='json')
def export_data(query):
    qs = MyModel.objects.all()
    qs.query = query
...

您需要
解码
编码
查询。Django 2.1和芹菜4.2与以下代码配合使用:

query\u dump=pickle.dumps(queryset.query).decode('latin1'))
query=pickle.load(query\u dump.encode('latin1'))

在撰写本文时,使用Python 3.7+和Django 2.2,
pickle
转储/加载似乎可以工作。 最后它只缺少一个
queryset.update()

我试过这样的方法:

# packing
queryset = MyModel.objects.filter(...)
serialized_queryset = pickle.dumps(queryset.query)

# unpacking
restored = MyModel.objects.all()
restored.query = pickle.loads(serialized_queryset)
restored.update()

而且效果很好。还没有在芹菜任务中进行测试,但我认为它应该可以工作。

请发布一些您为完成此任务而编写的代码。你到底想在芹菜任务中做什么?谢谢,但是Queryset来自一个外部库,我希望我可以使用返回的Queryset,分离出它的过滤器,等等。我完全打算在运行任务后使用Django ORM执行查询,我只是不想腌制一个查询集。但是为什么你不能在芹菜任务中使用外部库呢?当您可以直接在芹菜任务中使用此外部库时,在web视图中构建它,然后跳转到芹菜任务,这有什么意义呢?它是从Django admin中的一个选择生成的,但过滤器并不简单。我已经看过了,Django admin看起来像是直接生成了过滤器对象——它们从来没有变成一个dict,在序列化并传递给芹菜之后,可以提供给
filter()
。如果有更简单的方法从列表视图捕获过滤器并将其转换为芹菜端的过滤器,那肯定会有所帮助。也许捕获整个URL并通过另一端的相关类方法传递它是一种方法,但仍然不清楚您想要实现什么。你能提供更多关于你的项目的细节,以及你正在使用这些管理过滤器做什么吗?很有趣,谢谢你的回答。这是否避免了使用pickle时的安全问题?感谢您的更新。您知道这是否适用于JSON序列化程序吗?
# packing
queryset = MyModel.objects.filter(...)
serialized_queryset = pickle.dumps(queryset.query)

# unpacking
restored = MyModel.objects.all()
restored.query = pickle.loads(serialized_queryset)
restored.update()