在执行之前,Django QuerySet序列化的JSON进行芹菜



我从外部库给我一个QuerySet,并且 - 由于QuerySets是懒惰的 - 我想在访问它之前将其序列化至JSON ,因此在DB中执行,因此可以在异步芹菜任务中执行。

我的问题是,是否有一种将QuerySet的基本要素表示为JSON的方法,所以我不必使用泡菜?

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

详细信息

此处的特定用例正在评估任务中的QuerySet,因此可以将结果导出到文件并倒在服务器上以供以后访问。

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

该请求是从Django管理员更改视图列表过滤器生成的。我已经尝试返回列表过滤器代码,但似乎它只是生成过滤对象 - 不适合JSON序列化。

我可以查看列表过滤器查询字符串并将所有键重新评估到QuerySet滤波器中,但是许多过滤器是SimpleListFilter类,也只需返回过滤器对象,并且不会在该滤波器中显示真正的QuerySet滤波器URL。我需要为这些过滤器重新创建逻辑,以获取可以序列化的夸尔格风格的过滤器。

django 1.11&芹菜3.0

可悲的是,这不再起作用。如果有人有任何有关如何正确序列化QuerySet或其各种过滤器和属性的信息,请让我知道。

原始答案

事实证明,my_queryset.query是在执行前序列化QuerySet的正确且安全的方法。

如果您只想腌制必要的信息即以后从数据库中重新创建QuerySet,则泡菜QuerySet 的查询属性。然后,您可以使用这样的代码重新创建原始QuerySet(没有加载任何结果(:

import pickle
query = pickle.loads(s)     # Assuming 's' is the pickled string.
qs = MyModel.objects.all()
qs.query = query            # Restore the original 'query'.

查询属性是一个不透明的对象。它代表了查询构造的内部,而不是公共API的一部分。但是,如下所述,泡菜并取消属性的内容是安全的(并得到了完全支持(。

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#pickling-querysets

这是关于使用Pickle的,但它当然也可以与JSON Serialials一起使用。

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

在写作时,使用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即可在芹菜任务中访问它。您可以使用Django模型并在任务本身中创建QuerySet。如果创建QuerySet的特定方式,则可以将QuerySet创建代码放在公共功能或类中,并在Web应用程序代码和芹菜任务中导入此共享代码。

没有理由避免在芹菜任务中使用django orm。

您需要decodeencode查询。使用 django 2.1 芹菜4.2 与此代码一起使用:

query_dump = pickle.dumps(queryset.query).decode('latin1')
query = pickle.loads(query_dump.encode('latin1'))

相关内容

  • 没有找到相关文章

最新更新