在 Django 1.11 中将 QuerySet 传递给 Celery 任务
Pass QuerySet to Celery Task in Django 1.11
我想将一些长查询移动到 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 任务? 现在它会抛出无法完成的错误。
我有 可以在这里使用 pickle
,但我无法获得正确的使用方法。特别是 - query = pickle.loads(s)
中的 # Assuming 's' is the pickled string.
是什么意思。
如您所见,您无法将查询集直接传递给任务,因为任务参数必须是可序列化的。腌制也不是一个好的理想选择,因为您实际上不需要序列化整个查询集。
相反,您应该将对象 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'))
我想将一些长查询移动到 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 任务? 现在它会抛出无法完成的错误。
我有 pickle
,但我无法获得正确的使用方法。特别是 - query = pickle.loads(s)
中的 # Assuming 's' is the pickled string.
是什么意思。
如您所见,您无法将查询集直接传递给任务,因为任务参数必须是可序列化的。腌制也不是一个好的理想选择,因为您实际上不需要序列化整个查询集。
相反,您应该将对象 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'))