Как перехватить исключение OperationalError, возникающее в основном потоке django

Я использую базу данных Postgres 16.2 в моем проекте Django 5.0, настроенную следующим образом:

### settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'DB_NAME',
        'USER': 'DB_USER',
        'PASSWORD': 'DB_PASS',
        'HOST': 'DB_HOST',
        'PORT': '5432',
    }
}

Работает хорошо, никаких проблем нет.

Однако, когда я имитирую отключение базы данных (обычно я останавливаю службу базы данных на своем компьютере), я получаю исключение, которое мне не удается поймать:

Исключение брошено в потоке django-main-thread перед входом в представление.

Я пытался использовать промежуточное ПО, но это не помогает:

from django.db.utils import OperationalError
from django.utils.deprecation import MiddlewareMixin
from rest_framework import status
from rest_framework.response import Response


class OperationalErrorMiddleware(MiddlewareMixin):
    def __init__(self, get_response):
        super().__init__(get_response)

    def __call__(self, request):
        try:
            return self.get_response(request)
        except OperationalError:
            return Response({'status': "DB_ERROR"}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

Я также пытался использовать обработчики Django handler500 и DRF (Django REST Framework) EXCEPTION_HANDLER, но и эти обработчики не перехватывают исключение.

Это исключение приводит к пустому ответу для клиента (ERR_EMPTY_RESPONSE в Chrome), что плохо.

Как я могу поймать это исключение, чтобы показать более "удобную" ошибку?

В трассировке есть self.check_migrations() - это происходит еще до того, как ваш сервер запущен, чтобы правильно принимать соединения, когда Django проверяет, должен ли он показать вам сообщение "у вас N миграций, которые не были запущены".

На рабочем сервере, таком как uwsgi или gunicorn, этого не произойдет (потому что эти проверки выполняются только на сервере разработки runserver), и поэтому я не вижу причин, чтобы вы пытались справиться с этой конкретной ошибкой.

Вернуться на верх