如何在DRF的Serializer Validate函数中返回404状态码?
解决DRF序列化器validate返回404状态码的问题
你当前的写法无法改变响应状态码的原因是:Django REST Framework(DRF)默认会将序列化器抛出的ValidationError统一捕获,并返回400状态码,即使你给ValidationError指定了code=404,这个code只是错误码标识,并非HTTP响应状态码。
要实现验证失败时返回404状态码,可以通过以下两种方式处理:
方法一:在视图中手动捕获验证异常并返回404
在视图的业务逻辑方法(如create、update)中,调用序列化器的is_valid()时捕获ValidationError,判断是否是你定义的特定错误,然后手动返回404响应。
示例代码:
from rest_framework.response import Response from rest_framework import status from rest_framework.generics import CreateAPIView from .serializers import MySerializer class MyView(CreateAPIView): serializer_class = MySerializer def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) try: serializer.is_valid(raise_exception=True) except ValidationError as e: # 判断是否是我们需要返回404的错误 if e.detail.get('detail') == 'Not found.' or getattr(e, 'code', None) == 404: return Response(e.detail, status=status.HTTP_404_NOT_FOUND) # 其他验证错误保持默认400状态码 return Response(e.detail, status=status.HTTP_400_BAD_REQUEST) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
方法二:全局自定义异常处理器
通过DRF的全局异常处理机制,识别特定的ValidationError,修改响应状态码为404。
步骤1:编写自定义异常处理函数
在项目的工具文件(如utils.py)中添加以下代码:
from rest_framework.views import exception_handler from rest_framework import status from rest_framework.exceptions import ValidationError def custom_exception_handler(exc, context): # 先调用DRF默认的异常处理,获取基础响应对象 response = exception_handler(exc, context) # 针对ValidationError做特殊处理 if isinstance(exc, ValidationError) and response is not None: # 检查错误详情或code是否匹配我们的404标识 if exc.detail.get('detail') == 'Not found.' or getattr(exc, 'code', None) == 404: response.status_code = status.HTTP_404_NOT_FOUND return response
步骤2:在settings.py中配置自定义处理器
修改项目的settings.py,指定DRF使用自定义的异常处理函数:
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'your_project_name.utils.custom_exception_handler' }
补充说明
如果你的场景是检查对象是否存在,更符合DRF设计规范的方式是在视图的get_object()方法中抛出NotFound异常,这样会直接返回404状态码。但如果确实需要在序列化器的validate方法中触发404响应,上述两种方法都可以实现需求。
内容的提问来源于stack exchange,提问作者Waleed Farrukh
相关产品推荐
相关产品推荐

