Добавьте пользовательские поля в Django rest_framework APIException - PullRequest
1 голос
/ 01 апреля 2020

Я создаю подкласс класса APIException остальной структуры Django для создания пользовательских исключений API. Например, одно из моих исключений выглядит так:

class Unauthorized(APIException):
    status_code = 401
    default_detail = 'You have to login first.'
    default_code = 'ERR_UNAUTHORIZED'

И я написал собственный обработчик исключений для изменения имен ключей. Это часть в моем обработчике исключений, которая имеет дело с такими видами исключений:

def custom_exception_handler(exc, context):
     response.data['code'] = response.data['detail'].code
     response.data['message'] = response.data['detail']
     print(response.data)
     del response.data['detail']
     return response

В результате выходные данные для моих исключений выглядят так:

{
    "code": "ERR_UNAUTHORIZED",
    "message": "You have to login first."
}

Что мне нужно чтобы сделать это, я хочу добавить новое поле в мои исключения, чтобы вывод моих исключений стал похож на следующий пример:

{
    "code": "ERR_UNAUTHORIZED",
    "message": "You have to login first.",
    "extra" : "{ "description" : "extra info" }"
}

И в моих представлениях я хочу выбросить это исключение следующим образом:

raise Unauthorized(extra={ "description" : "extra info" })

Я довольно новичок в Django rest_framework, я искал об этом, а также пытался добавить "another field" в мои поля класса пользовательских исключений, но это не решило мою проблему. Есть ли способы сделать что-то подобное?

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

Я нашел ответ сам (который не очень чистый). Мы можем генерировать исключения в наших сериализаторах, как показано ниже:

 raise serializers.ValidationError({"info" : "test info"})

И в обработчике пользовательских исключений мы можем обработать этот сценарий следующим образом:

def custom_exception_handler(exc, context):

    response = exception_handler(exc, context)

    if isinstance(exc, ValidationError): 
        resp_copy = response.data
        del response.data
        response.data = {}
        if(response.status_code == 400):
            response.data['code'] = 'ERR_UNAUTHORIZED'
            response.data['message'] = 'some errors occurred'
            response.data['extra'] = {}
            for key in resp_copy:
                response.data['extra'][key] = resp_copy[key]

Вывод будет в форме ниже :

{
    "code": "ERR_UNAUTHORIZED",
    "message": "some errors occurred",
    "extra": {
        "info": [
            "test info"
        ]
    }
}
0 голосов
/ 03 апреля 2020

Попробуйте вот так

def custom_exception_handler(exc, context):
     response.data['code'] = response.data['detail'].code
     response.data['message'] = response.data['detail']

     response.data['another_field'] = { "description" : "extra info" }

     print(response.data)
     del response.data['detail']
     return response

Надеюсь, это поможет вам ....

Дополнительный ответ

class Unauthorized(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

Поднимите исключение, где вы хотите

raise Unauthorized("Your message")

И поймать исключение

try:
    ...
except Unauthorized as e:
    print(str(e))
...