Django-Styleguide/utils.py
2018-12-28 19:24:43 +02:00

61 lines
1.7 KiB
Python

from rest_framework import serializers
from rest_framework import exceptions as rest_exceptions
from django.core.exceptions import ValidationError
def create_serializer_class(name, fields):
return type(name, (serializers.Serializer, ), fields)
def inline_serializer(*, fields, data=None, **kwargs):
serializer_class = create_serializer_class(name='', fields=fields)
if data is not None:
return serializer_class(data=data, **kwargs)
return serializer_class(**kwargs)
def get_first_matching_attr(obj, *attrs, default=None):
for attr in attrs:
if hasattr(obj, attr):
return getattr(obj, attr)
return default
def get_error_message(exc):
if hasattr(exc, 'message_dict'):
return exc.message_dict
error_msg = get_first_matching_attr(exc, 'message', 'messages')
if isinstance(error_msg, list):
error_msg = ', '.join(error_msg)
if error_msg is None:
error_msg = str(exc)
return error_msg
class ExceptionHandlerMixin:
"""
Mixin that transforms Django and Python exceptions into rest_framework ones.
without the mixin, they return 500 status code which is not desired.
"""
expected_exceptions = {
ValueError: rest_exceptions.ValidationError,
ValidationError: rest_exceptions.ValidationError,
PermissionError: rest_exceptions.PermissionDenied
}
def handle_exception(self, exc):
if isinstance(exc, tuple(self.expected_exceptions.keys())):
drf_exception_class = self.expected_exceptions[exc.__class__]
drf_exception = drf_exception_class(get_error_message(exc))
return super().handle_exception(drf_exception)
return super().handle_exception(exc)