【问题标题】:Catch all exceptions in django rest framework捕获 django rest 框架中的所有异常
【发布时间】:2018-07-23 07:01:09
【问题描述】:

我想这更像是一个代码质量问题,但它确实涉及处理未处理的异常是 Django REST 框架。

删除受保护的记录只返回<h1>500 internal server error<h1> 所以我添加了示例自定义异常处理程序。第一行返回一个无响应。

response = exception_handler(exc, context)

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status

def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)

    if response is None:
        #DRF could not process the exception so we will treat it as a 500 and try to get the user as much info as possible.
        response = Response({'error': str(exc)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

return response

所以在这种情况下,我将其视为 500,因为 DRF 无法处理 exc

我想我的问题是这是一种适当的处理方式吗?有没有人有这方面的经验有更好的解决方案?

更新:

Traceback:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
115.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
54.         return view_func(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/viewsets.py" in view
116.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
495.             response = self.handle_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception
455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
492.             response = handler(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/mixins.py" in create
21.         self.perform_create(serializer)

File "/device_mgmt/selection/views.py" in perform_create
84.             serializer.save(realm=utils.get_realm_from_request(self.request))

File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py" in save
214.             self.instance = self.create(validated_data)

File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py" in create
943.             instance = ModelClass._default_manager.create(**validated_data)

File "/usr/local/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in create
422.         obj.save(force_insert=True, using=self.db)

File "/device_mgmt/selection/models.py" in save
123.         self.full_clean()

File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py" in full_clean
1203.             raise ValidationError(errors)

Exception Type: ValidationError at /company/api/company/
Exception Value: {'id': ['Company with this Id already exists.']}

Django 模型抛出验证错误,但其余框架视图将其称为未捕获。

【问题讨论】:

    标签: django exception django-rest-framework


    【解决方案1】:

    这似乎是我要找的东西......

    https://gist.github.com/twidi/9d55486c36b6a51bdcb05ce3a763e79f

    基本将django异常转化为drf异常,细节相同。

    """
    Sometimes in your Django model you want to raise a ``ValidationError`` 
    in the ``save`` method, for
    some reason.
    This exception is not managed by Django Rest Framework because it 
    occurs after its validation 
    process. So at the end, you'll have a 500.
    Correcting this is as simple as overriding the exception handler, by 
    converting the Django
    ``ValidationError`` to a DRF one.
    """
    
    from django.core.exceptions import ValidationError as 
    DjangoValidationError
    
    from rest_framework.exceptions import ValidationError as 
    DRFValidationError
    from rest_framework.views import exception_handler as 
    drf_exception_handler
    
    
    def exception_handler(exc, context):
        """Handle Django ValidationError as an accepted exception
        Must be set in settings:
        >>> REST_FRAMEWORK = {
        ...     # ...
        ...     'EXCEPTION_HANDLER': 'mtp.apps.common.drf.exception_handler',
        ...     # ...
        ... }
        For the parameters, see ``exception_handler``
        """
    
        if isinstance(exc, DjangoValidationError):
            if hasattr(exc, 'message_dict'):
                exc = DRFValidationError(detail={'error': exc.message_dict})
            elif hasattr(exc, 'message'):
                exc = DRFValidationError(detail={'error': exc.message})
            elif hasattr(exc, 'messages'):
                exc = DRFValidationError(detail={'error': exc.messages})
    
        return drf_exception_handler(exc, context)
    

    这对我有用,现在我收到了包含相关详细信息的 500 响应,而不是通用的 500 响应。

    【讨论】:

      【解决方案2】:

      您可以使用Django REST Framework exceptions

      在您的具体情况下,您可能希望使用NotFound

      from rest_framework.exceptions import NotFound
      
      # something bad happens
      raise NotFound('User Message')
      

      NotFound 默认会抛出 404 错误,你可以添加 500。

      raise NotFound('User Message', code=500)
      

      其他异常的使用方法相同。

      【讨论】:

      • 抱歉,我没有发布堆栈跟踪,但它确实直接影响了我的视图集。这一切都发生在后台。
      • 然后需要堆栈跟踪和更多详细信息 -- 不清楚您的问题是什么/在哪里
      • 或者你可以提出exceptions.APIException。对于以后的版本,我们在code 属性中使用字符串值而不是数字,所以code=500 将是code="error"
      猜你喜欢
      • 2019-03-05
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      相关资源
      最近更新 更多