Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't want drf ValidationError response to be textual. How to do that?

I'm using django rest framework. How do I change the DRF ValidationError detail not to be textual? For example:

raise  ValidationError(detail={"something": True})

response:

{
    "something": "True"
}

expected response:

{
    "something": true
}
like image 843
Milad Khodabandehloo Avatar asked Sep 17 '25 22:09

Milad Khodabandehloo


1 Answers

In rest_framework/exceptions.py:

class ValidationError(APIException):
    status_code = status.HTTP_400_BAD_REQUEST
    default_detail = _('Invalid input.')
    default_code = 'invalid'

    def __init__(self, detail=None, code=None):
        if detail is None:
            detail = self.default_detail
        if code is None:
            code = self.default_code

        # For validation failures, we may collect many errors together,
        # so the details should always be coerced to a list if not already.
        if not isinstance(detail, dict) and not isinstance(detail, list):
            detail = [detail]

        self.detail = _get_error_details(detail, code)

As you can see function _get_error_details(detail, code) gets called to manipulate your detail:

def _get_error_details(data, default_code=None):
    """
    Descend into a nested data structure, forcing any
    lazy translation strings or strings into `ErrorDetail`.
    """
    if isinstance(data, list):
        ret = [
            _get_error_details(item, default_code) for item in data
        ]
        if isinstance(data, ReturnList):
            return ReturnList(ret, serializer=data.serializer)
        return ret
    elif isinstance(data, dict):
        ret = {
            key: _get_error_details(value, default_code)
            for key, value in data.items()
        }
        if isinstance(data, ReturnDict):
            return ReturnDict(ret, serializer=data.serializer)
        import pdb
        pdb.set_trace()
        return ret

    text = force_text(data)
    code = getattr(data, 'code', default_code)
    return ErrorDetail(text, code)

This is where your boolean becomes string (text = force_text(data) part). One way to overcome this is to overwrite the ValidationError class with self.detail = detail instead of self.detail = _get_error_details(detail, code). Although I wouldnt suggest doing this and just sticking with the default behaviour.

like image 181
Toni Sredanović Avatar answered Sep 22 '25 13:09

Toni Sredanović