Skip to content

Instantly share code, notes, and snippets.

@bay007
Last active August 22, 2020 07:10
Show Gist options
  • Save bay007/09d11729a85245de5e9139aaacf49606 to your computer and use it in GitHub Desktop.
Save bay007/09d11729a85245de5e9139aaacf49606 to your computer and use it in GitHub Desktop.
from collections import OrderedDict
from rest_framework.response import Response
from rest_framework.exceptions import ErrorDetail
class ErrorResponse:
def __init__(self, error: list) -> None:
self.__error = error
@property
def data(self) -> dict:
return {"error": self.__error}
def render(response):
response._is_rendered = False
response.render()
return response
class ParserResponse:
"""Custom Responses fro DRF
Ejemplo 1:
Si el errror de salida nativo de DRF es por ejemplo:
```
{
"error__phone_number": [
"Phone number must have 10 or 11 digits"
],
"error__email": [
"User with this email address already exists."
],
"error__password": [
"The password is too similar to the first name.",
"This password is too short. It must contain at least 10 characters."
]
}
```
A la salida en postman obtendrías:
```
{
"errors": [
"Phone number must have 10 or 11 digits",
"User with this email address already exists.",
"The password is too similar to the first name.",
"This password is too short. It must contain at least 10 characters."
]
}
```
Ejemplo 2:
Si el errror de salida nativo de DRF es por ejemplo:
```
{
"non_field_errors": [
"You don´t have an active subscription.",
"Tou can pass only with 500 credits"
]
}
```
A la salida en postman obtendrías:
```
{
"errors": [
"You don´t have an active subscription.",
"Tou can pass only with 500 credits"
]
}
```
Ejemplo 3:
Si el errror de salida nativo de DRF es por ejemplo:
```
{
"detail": "You not have credentials for connect."
}
```
A la salida en postman obtendrías:
```
{
"errors": [
"You not have credentials for connect."
]
}
or
{
'facturas_ids': {
0: [
ErrorDetail(string='A valid integer is required.', code='invalid')
]
}
}
```
"""
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def error_normalizer(self, error_detail, depth=20):
if depth == 1:
return error_detail
result = []
def transform(value):
r = self.error_normalizer(value, depth-1)
if isinstance(value, ErrorDetail):
r = str(r)
if isinstance(r, (list,tuple)):
result.extend(r)
else:
result.append(r)
return list(OrderedDict.fromkeys(result))
if isinstance(error_detail, str) and not isinstance(error_detail, ErrorDetail):
return [error_detail]
elif isinstance(error_detail, tuple):
for element in error_detail:
result = transform(element)
return result
elif isinstance(error_detail, list):
for element in error_detail.copy():
result = transform(element)
return result
elif isinstance(error_detail, dict):
for value in error_detail.copy().values():
result = transform(value)
return result
else:
return error_detail
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
if isinstance(response, Response):
if response.status_code >= 200 and response.status_code < 400:
return response
if response.status_code >= 400:
try:
data = response.data.copy()
except Exception as identifier:
data = response
new_data = self.error_normalizer(data)
error = ErrorResponse(new_data)
response.data = error.data
return render(response)
return response
return response
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment