Adding params to error details

This commit is contained in:
kieffer julien 2020-08-28 11:24:59 +02:00
parent 7f3a3557a0
commit d1b8511f91
3 changed files with 32 additions and 13 deletions

View File

@ -38,7 +38,8 @@ def _get_error_details(data, default_code=None):
text = force_str(data) text = force_str(data)
code = getattr(data, 'code', default_code) code = getattr(data, 'code', default_code)
return ErrorDetail(text, code) params = getattr(data, 'params', tuple())
return ErrorDetail(text, code, params)
def _get_codes(detail): def _get_codes(detail):
@ -54,10 +55,16 @@ def _get_full_details(detail):
return [_get_full_details(item) for item in detail] return [_get_full_details(item) for item in detail]
elif isinstance(detail, dict): elif isinstance(detail, dict):
return {key: _get_full_details(value) for key, value in detail.items()} return {key: _get_full_details(value) for key, value in detail.items()}
return {
_base = {
'message': detail, 'message': detail,
'code': detail.code 'code': detail.code
} }
params = getattr(detail, "params", None)
if params:
_base.update({"params": params})
return _base
class ErrorDetail(str): class ErrorDetail(str):
@ -65,10 +72,12 @@ class ErrorDetail(str):
A string-like object that can additionally have a code. A string-like object that can additionally have a code.
""" """
code = None code = None
params = None
def __new__(cls, string, code=None): def __new__(cls, string, code=None, params=None):
self = super().__new__(cls, string) self = super().__new__(cls, string)
self.code = code self.code = code
self.params = params
return self return self
def __eq__(self, other): def __eq__(self, other):
@ -82,11 +91,13 @@ class ErrorDetail(str):
return not self.__eq__(other) return not self.__eq__(other)
def __repr__(self): def __repr__(self):
return 'ErrorDetail(string=%r, code=%r)' % ( base = 'ErrorDetail(string=%r, code=%r' % (
str(self), str(self),
self.code, self.code,
) )
return base + ', params=%r)' % self.params if self.params else base + ')'
def __hash__(self): def __hash__(self):
return hash(str(self)) return hash(str(self))
@ -105,7 +116,6 @@ class APIException(Exception):
detail = self.default_detail detail = self.default_detail
if code is None: if code is None:
code = self.default_code code = self.default_code
self.detail = _get_error_details(detail, code) self.detail = _get_error_details(detail, code)
def __str__(self): def __str__(self):
@ -141,6 +151,7 @@ class ValidationError(APIException):
default_code = 'invalid' default_code = 'invalid'
def __init__(self, detail=None, code=None): def __init__(self, detail=None, code=None):
print(detail, code)
if detail is None: if detail is None:
detail = self.default_detail detail = self.default_detail
if code is None: if code is None:

View File

@ -236,12 +236,14 @@ def get_error_detail(exc_info):
except AttributeError: except AttributeError:
return [ return [
ErrorDetail((error.message % error.params) if error.params else error.message, ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code) code=error.code if error.code else code,
params=error.params)
for error in exc_info.error_list] for error in exc_info.error_list]
return { return {
k: [ k: [
ErrorDetail((error.message % error.params) if error.params else error.message, ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code) code=error.code if error.code else code,
params=error.params)
for error in errors for error in errors
] for k, errors in error_dict.items() ] for k, errors in error_dict.items()
} }
@ -599,6 +601,7 @@ class Field:
raise raise
errors.extend(exc.detail) errors.extend(exc.detail)
except DjangoValidationError as exc: except DjangoValidationError as exc:
print("YOOOOOOOOOO", exc, exc.code, exc.params)
errors.extend(get_error_detail(exc)) errors.extend(get_error_detail(exc))
if errors: if errors:
raise ValidationError(errors) raise ValidationError(errors)

View File

@ -12,17 +12,17 @@ factory = APIRequestFactory()
class ExampleSerializer(serializers.Serializer): class ExampleSerializer(serializers.Serializer):
char = serializers.CharField() char = serializers.CharField()
integer = serializers.IntegerField() integer = serializers.IntegerField(min_value=1, required=False)
class ErrorView(APIView): class ErrorView(APIView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
ExampleSerializer(data={}).is_valid(raise_exception=True) ExampleSerializer(data={"integer": 0}).is_valid(raise_exception=True)
@api_view(['GET']) @api_view(['GET'])
def error_view(request): def error_view(request):
ExampleSerializer(data={}).is_valid(raise_exception=True) ExampleSerializer(data={"integer": 0}).is_valid(raise_exception=True)
class TestValidationErrorWithFullDetails(TestCase): class TestValidationErrorWithFullDetails(TestCase):
@ -41,8 +41,13 @@ class TestValidationErrorWithFullDetails(TestCase):
'code': 'required', 'code': 'required',
}], }],
'integer': [{ 'integer': [{
'message': 'This field is required.', 'message': 'Ensure this value is greater than or equal to 1.',
'code': 'required' 'code': 'min_value',
'params': {
'limit_value': 1,
'show_value': 0,
'value': 0
}
}], }],
} }
@ -78,7 +83,7 @@ class TestValidationErrorWithCodes(TestCase):
self.expected_response_data = { self.expected_response_data = {
'char': ['required'], 'char': ['required'],
'integer': ['required'], 'integer': ['min_value'],
} }
def tearDown(self): def tearDown(self):