django 如何通过一系列方法传递use sync_to_async

xwbd5t1u  于 2023-03-04  发布在  Go
关注(0)|答案(1)|浏览(200)

我有这样一个案例:

async def handler(self):
   await sync_to_async(Stock.objects.filter)(id__in=product_stock).update(is_filled=False)

我尝试将product_stock传递给filter方法,然后在过滤后的queryset上调用update。我知道我可以将逻辑封装在另一个方法中,并只传递arg,如下所示:

@classmethod
def update_stocks(
    cls, product_stock: List[uuid.UUID]
) -> None:
    """Update stocks for order products."""
    cls.objects.filter(id__in=product_stock).update(is_filled=False)

async def handler(self):
   await sync_to_async(Stock.update_stocks)(product_stock=product_stock)

但是有可能像我上面的尝试那样做这一切,当然这是行不通的,因为结果是一个courotine而不是一个django查询集?如果可能的话,我想避免使用另一种方法。

pepwfjgg

pepwfjgg1#

我不是Django用户,但我认为这是一个操作符优先级的问题。sync_to_async函数返回另一个函数(异步函数),所以为了清晰起见,假设你的第一个处理函数如下所示:

async def handler(self):
    f = sync_to_async(Stock.objects.filter)
    await f(id__in=product_stock).update()

由于await的结合比.弱,最后一行等价于:

await (f(id__in=product_stock).update())

这不是我们想要的,因为f()的返回值是一个协程,所以它没有update()方法。
您所需要的是这样的,它将update()调用应用于协程f的返回值:

(await f(id__in=product_stock)).update()

或者,回到你最初的方法:

(await sync_to_async(Stock.objects.filter)(id__in=product_stock)).update(is_filled=False)

老实说,我认为所有这些括号都很难看,而且我可能更喜欢有额外函数的方法。但这是一个品味的问题。我认为它应该起作用。

相关问题