将QuerySet传递给Django 1.11中的Celery Task

时间:2018-04-20 18:31:11

标签: python django asynchronous celery pickle

我想将一些长查询移动到Celery中的异步任务,然后使用AJAX检索该额外信息。现在我得到这样的QuerySet:

brands = Brand.objects.filter(shops__shop_name__in=[shop])

任务:

@task()
def brand_count(querystr):
    querystr.annotate(amount_of_products=Count('products'))

我想做here

task_run = brand_count.delay(brands)

问题是:如何将QuerySet传递给Celery任务?现在它抛出了一个无法完成的错误。

found pickle可能会在这里使用,但我无法正确使用它。特别是 - # Assuming 's' is the pickled string.中的query = pickle.loads(s)意味着什么。

1 个答案:

答案 0 :(得分:0)

正如您所发现的,您无法直接将查询集传递给任务,因为任务参数必须是可序列化的。由于您实际上不需要序列化整个查询集,因此酸洗不是一个好理想。

相反,您应该将对象ID列表传递给任务,然后从任务本身获取查询集。

brand_ids = Brand.objects.filter(shops__shop_name__in=[shop]).values_list('id', flat=True)
task_run = brand_count.delay(list(brand_ids))

values_list会为您提供品牌ID列表。

然后,在您的任务中,您重新创建查询集并使用它执行所需操作:

@task()
def brand_count(brand_ids):
    queryset = Brand.objects.filter(id__in=brand_ids)
    queryset.annotate(amount_of_products=Count('products'))