Django 4.x中如何返回JSON格式的404和500错误而非默认HTML页面
解决DRF自定义异常处理器仍返回HTML页面的问题
核心原因
你的自定义异常处理器仅对DRF视图抛出的APIException子类异常生效,以下场景会触发Django原生异常逻辑,返回HTML页面:
- 访问未配置的路由(Django全局404)
- 使用普通Django视图而非DRF视图类
- 底层异常未被DRF捕获(如数据库直接抛出的错误)
具体解决方案
1. 覆盖Django全局异常处理,统一返回JSON
在项目根目录新建error_views.py(或复用现有views.py),添加全局错误处理视图:
from django.http import JsonResponse def json_404_handler(request, exception): return JsonResponse({"code": 404, "message": "请求的资源不存在"}, status=404) def json_500_handler(request): return JsonResponse({"code": 500, "message": "服务器内部错误"}, status=500)
然后在项目根urls.py中覆盖默认错误路由:
from .error_views import json_404_handler, json_500_handler handler404 = json_404_handler handler500 = json_500_handler
2. 确保所有业务视图使用DRF视图类
普通Django视图不会触发DRF的异常处理器,需将视图改为继承APIView或DRF视图集:
from rest_framework.views import APIView from rest_framework.response import Response class BusinessView(APIView): def get(self, request): # 业务逻辑代码 return Response({"data": "正常返回内容"})
3. 完善DRF异常处理器,捕获更多异常
修改exceptions.py,处理DRF未覆盖的Django原生异常:
from rest_framework.views import exception_handler from rest_framework.response import Response from rest_framework import status from django.core.exceptions import ObjectDoesNotExist def custom_exception_handler(exc, context): # 先调用DRF默认异常处理器 response = exception_handler(exc, context) # 处理DRF未捕获的异常 if response is None: if isinstance(exc, ObjectDoesNotExist): return Response({"code": 404, "message": "指定资源不存在"}, status=status.HTTP_404_NOT_FOUND) # 其他未捕获异常统一返回500 return Response({"code": 500, "message": "服务器内部错误"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # 重写DRF已捕获异常的返回格式 if response.status_code == 500: response.data = {"code": 500, "message": "服务器内部错误"} if response.status_code == 404: response.data = {"code": 404, "message": "请求的资源不存在"} return response
4. 强制DRF返回JSON格式
在settings.py中修改渲染器配置,优先返回JSON:
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'backend.exceptions.custom_exception_handler', 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', # 若需要保留浏览器可查看的API调试页面,可保留下面一行 # 'rest_framework.renderers.BrowsableAPIRenderer', ], }
内容的提问来源于stack exchange,提问作者lolz
相关产品推荐
相关产品推荐

