Search code examples
pythondjangodatabaseexceptiontransactions

What is the simplest way to retry a Django view upon an exception being raised?


I want to rerun a Django view function if a certain exception is raised (in my case a serialization error in the underlying database). I want it to run with exactly the same parameters, including the same request object - as if the client had re-requested the URL.

There are many database queries in the view, and the exception could be raised on any one of them - and it won't work to rerun just one of the queries in isolation, so I think I need to wrap the entire view function in a try/except block and loop until success.

But, I have several view functions which might raise such exceptions, so I want a generic solution. I also want to be able to retry up to a certain number of times and then fail.

Is there any simple solution?


Solution

  • You could achieve this by writing a decorator:

    def retry_on_exception(view):
        def wrapper(*args, **kwargs):
            while True:
                try:
                    return view(*args, **kwargs):
                except (TheExceptions, IWant, ToCatch):
                    pass
        return wrapper
    

    And use this on the view:

    @retry_on_exception
    def my_view(request, foo, bar):
        return HttpResponse("My stuff")
    

    Obviously, this will retry indefinitely, so a lot of logic could be improved there. You could also write the decorator to accept the exceptions it wants to look out for, so you can customise it per view.