如何捕获django-main-thread中抛出的Django OperationalError异常
解决Django启动时数据库连接异常无法捕获的问题
问题原因
你遇到的异常发生在服务器启动阶段(runserver执行check_migrations步骤),这个阶段早于请求处理流程,所以常规的中间件、handler500、DRF异常处理器都无法捕获——它们只在处理单个请求时生效。
解决方案
1. 自定义runserver命令,避免启动时崩溃
创建management/commands/runserver.py文件,重写默认的runserver命令,捕获迁移检查时的数据库异常,让服务器能正常启动:
from django.core.management.commands.runserver import Command as RunserverCommand from django.db.utils import OperationalError class Command(RunserverCommand): def inner_run(self, *args, **options): try: # 尝试执行原有的启动流程(包括迁移检查) super().inner_run(*args, **options) except OperationalError as e: self.stdout.write(self.style.ERROR(f"数据库连接失败: {str(e)}")) self.stdout.write(self.style.WARNING("服务器将继续运行,无法处理依赖数据库的请求")) # 跳过迁移检查,直接启动HTTP服务器 self.start_http_server(*args, **options)
2. 配置中间件捕获请求阶段的异常
更新中间件为Django 5.0推荐的写法(无需MiddlewareMixin),确保能捕获请求处理时的数据库连接异常:
from django.db.utils import OperationalError from rest_framework import status from rest_framework.response import Response class OperationalErrorMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): try: return self.get_response(request) except OperationalError: return Response( {'status': "DB_ERROR", 'message': "数据库服务暂时不可用"}, status=status.HTTP_503_SERVICE_UNAVAILABLE )
在settings.py的MIDDLEWARE列表中添加这个中间件(建议放在靠近顶部的位置,确保优先捕获异常):
MIDDLEWARE = [ # ...其他中间件 'your_app.middleware.OperationalErrorMiddleware', # ...其他中间件 ]
3. 生产环境注意事项
生产环境使用gunicorn或uwsgi启动时,默认不会自动执行迁移检查,因此服务器不会因数据库连接失败而启动崩溃。此时只需确保中间件配置正确,即可在请求时返回友好的503响应。
内容的提问来源于stack exchange,提问作者GuiTeK
相关产品推荐
相关产品推荐

