mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 20:16:44 +00:00
Adds a custom exception handler for DRF
- Handles common exceptions not captured by DRF - Returns exeption data as a JSON object
This commit is contained in:
parent
ea2fb76a29
commit
1488a0e72f
80
InvenTree/InvenTree/exceptions.py
Normal file
80
InvenTree/InvenTree/exceptions.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
"""
|
||||||
|
Custom exception handling for the DRF API
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from django.db.utils import OperationalError, ProgrammingError, IntegrityError
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from error_report.models import Error
|
||||||
|
|
||||||
|
from rest_framework.exceptions import ValidationError as DRFValidationError
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import serializers
|
||||||
|
import rest_framework.views as drfviews
|
||||||
|
|
||||||
|
|
||||||
|
def exception_handler(exc, context):
|
||||||
|
"""
|
||||||
|
Custom exception handler for DRF framework.
|
||||||
|
Ref: https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling
|
||||||
|
|
||||||
|
Catches any errors not natively handled by DRF, and re-throws as an error DRF can handle
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = None
|
||||||
|
|
||||||
|
# Catch any django validation error, and re-throw a DRF validation error
|
||||||
|
if isinstance(exc, DjangoValidationError):
|
||||||
|
exc = DRFValidationError(detail=serializers.as_serializer_error(exc))
|
||||||
|
|
||||||
|
# Exceptions we will manually check for here
|
||||||
|
handled_exceptions = [
|
||||||
|
IntegrityError,
|
||||||
|
OperationalError,
|
||||||
|
ProgrammingError,
|
||||||
|
ValueError,
|
||||||
|
TypeError,
|
||||||
|
NameError,
|
||||||
|
]
|
||||||
|
|
||||||
|
if any([isinstance(exc, err_type) for err_type in handled_exceptions]):
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
error_detail = str(exc)
|
||||||
|
else:
|
||||||
|
error_detail = _("Error details can be found in the admin panel")
|
||||||
|
|
||||||
|
response_data = {
|
||||||
|
'error': type(exc).__name__,
|
||||||
|
'error_class': str(type(exc)),
|
||||||
|
'detail': error_detail,
|
||||||
|
'path': context['request'].path,
|
||||||
|
'status_code': 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = Response(response_data, status=500)
|
||||||
|
|
||||||
|
# Log the exception to the database, too
|
||||||
|
Error.objects.create(
|
||||||
|
kind="Unhandled DRF API Exception",
|
||||||
|
info=str(type(exc)),
|
||||||
|
data=str(exc),
|
||||||
|
path=context['request'].path,
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Fallback to the default DRF exception handler
|
||||||
|
response = drfviews.exception_handler(exc, context)
|
||||||
|
|
||||||
|
if response is not None:
|
||||||
|
# For an error response, include status code information
|
||||||
|
response.data['status_code'] = response.status_code
|
||||||
|
|
||||||
|
return response
|
@ -353,7 +353,7 @@ TEMPLATES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
|
'EXCEPTION_HANDLER': 'InvenTree.exceptions.exception_handler',
|
||||||
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
|
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
'rest_framework.authentication.BasicAuthentication',
|
'rest_framework.authentication.BasicAuthentication',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user