我希望在出现异常时(在我的例子中是底层数据库中的序列化错误)重新运行Django视图函数,并希望它使用完全相同的参数运行,包括相同的request
对象-就像客户端重新请求了URL一样。
视图中有许多数据库查询,其中任何一个都可能引发异常--只孤立地重新运行其中一个查询是行不通的,所以我认为需要将整个视图函数 Package 在try/except块和循环中,直到成功。
但是,我有几个视图函数可能会引发这样的异常,所以我希望有一个通用的解决方案。我还希望能够重试一定的次数,然后失败。
有什么简单的解决办法吗?
2条答案
按热度按时间jum4pzuy1#
您可以通过编写一个装饰器来实现这一点:
并在视图上使用此命令:
显然,这将无限期地重试,因此许多逻辑可以改进,您也可以编写装饰器来接受它想要查找的异常,因此您可以为每个视图定制它。
rdrgkggo2#
您可以使用下面的
retry()
来重试视图零次或多次,间隔秒数为零或更多:例如,我有**
Person
模型如下。* 我使用PostgreSQL**:然后,除了每次出现**
IntegrityError
异常时的正常尝试之外,test()
视图**(带有以下@retry(4, 2)
)还可以重试4次(间隔为2秒),如下所示:如您所见,除了正常尝试之外,
test
视图还重试了4次,最后出现了**ValueError
异常**,因为返回了None
:并且,根据下面的PostgreSQL查询日志,事务运行了5次(浅蓝色为正常尝试,黄色为4次重试)。* 您可以检查如何记录PostgreSQL查询:
注意,如果装饰器的顺序是
@transaction.atomic
,则@retry(4, 2)
如下所示:出现以下错误:
store.models.Person.DoesNotExist:人员匹配查询不存在
因此,装饰器的顺序必须是
@retry(4, 2)
,然后是@transaction.atomic
,如下所示:默认情况下,
@retry
会重试**test()
视图2次,间隔为1秒,每次出现IntegrityError
异常**时,@retry
会进行一次正常尝试,如下所示:如您所见,除了正常尝试之外,
test
视图还重试了2次,然后最终出现**ValueError
异常**,因为返回了None
:并且,根据以下PostgreSQL查询日志,事务运行3次(浅蓝色为正常尝试,黄色为2次重试):
另外,如果您想在
@retry
正常尝试的基础上,以0.5秒的间隔默认重试**test()
view**3次,则需要分别将count = 2
更改为count = 3
,将interval=1
更改为interval=0.5
,如下所示: