mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	feat: Add some changes to ValidationError to support django style vadation errors (#8863)
This commit is contained in:
		
							parent
							
								
									22d206c1e0
								
							
						
					
					
						commit
						4abfa28e08
					
				| 
						 | 
				
			
			@ -144,17 +144,30 @@ class ValidationError(APIException):
 | 
			
		|||
    status_code = status.HTTP_400_BAD_REQUEST
 | 
			
		||||
    default_detail = _('Invalid input.')
 | 
			
		||||
    default_code = 'invalid'
 | 
			
		||||
    default_params = {}
 | 
			
		||||
 | 
			
		||||
    def __init__(self, detail=None, code=None):
 | 
			
		||||
    def __init__(self, detail=None, code=None, params=None):
 | 
			
		||||
        if detail is None:
 | 
			
		||||
            detail = self.default_detail
 | 
			
		||||
        if code is None:
 | 
			
		||||
            code = self.default_code
 | 
			
		||||
        if params is None:
 | 
			
		||||
            params = self.default_params
 | 
			
		||||
 | 
			
		||||
        # For validation failures, we may collect many errors together,
 | 
			
		||||
        # so the details should always be coerced to a list if not already.
 | 
			
		||||
        if isinstance(detail, tuple):
 | 
			
		||||
            detail = list(detail)
 | 
			
		||||
        if isinstance(detail, str):
 | 
			
		||||
            detail = [detail % params]
 | 
			
		||||
        elif isinstance(detail, ValidationError):
 | 
			
		||||
            detail = detail.detail
 | 
			
		||||
        elif isinstance(detail, (list, tuple)):
 | 
			
		||||
            final_detail = []
 | 
			
		||||
            for detail_item in detail:
 | 
			
		||||
                if isinstance(detail_item, ValidationError):
 | 
			
		||||
                    final_detail += detail_item.detail
 | 
			
		||||
                else:
 | 
			
		||||
                    final_detail += [detail_item % params if isinstance(detail_item, str) else detail_item]
 | 
			
		||||
            detail = final_detail
 | 
			
		||||
        elif not isinstance(detail, dict) and not isinstance(detail, list):
 | 
			
		||||
            detail = [detail]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,3 +109,89 @@ class TestValidationErrorConvertsTuplesToLists(TestCase):
 | 
			
		|||
        assert len(error.detail) == 2
 | 
			
		||||
        assert str(error.detail[0]) == 'message1'
 | 
			
		||||
        assert str(error.detail[1]) == 'message2'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestValidationErrorWithDjangoStyle(TestCase):
 | 
			
		||||
    def test_validation_error_details(self):
 | 
			
		||||
        error = ValidationError('Invalid value: %(value)s', params={'value': '42'})
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
 | 
			
		||||
    def test_validation_error_details_tuple(self):
 | 
			
		||||
        error = ValidationError(
 | 
			
		||||
            detail=('Invalid value: %(value1)s', 'Invalid value: %(value2)s'),
 | 
			
		||||
            params={'value1': '42', 'value2': '43'},
 | 
			
		||||
        )
 | 
			
		||||
        assert isinstance(error.detail, list)
 | 
			
		||||
        assert len(error.detail) == 2
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
        assert str(error.detail[1]) == 'Invalid value: 43'
 | 
			
		||||
 | 
			
		||||
    def test_validation_error_details_list(self):
 | 
			
		||||
        error = ValidationError(
 | 
			
		||||
            detail=['Invalid value: %(value1)s', 'Invalid value: %(value2)s', ],
 | 
			
		||||
            params={'value1': '42', 'value2': '43'}
 | 
			
		||||
        )
 | 
			
		||||
        assert isinstance(error.detail, list)
 | 
			
		||||
        assert len(error.detail) == 2
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
        assert str(error.detail[1]) == 'Invalid value: 43'
 | 
			
		||||
 | 
			
		||||
    def test_validation_error_details_validation_errors(self):
 | 
			
		||||
        error = ValidationError(
 | 
			
		||||
            detail=ValidationError(
 | 
			
		||||
                detail='Invalid value: %(value1)s',
 | 
			
		||||
                params={'value1': '42'},
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        assert isinstance(error.detail, list)
 | 
			
		||||
        assert len(error.detail) == 1
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
 | 
			
		||||
    def test_validation_error_details_validation_errors_list(self):
 | 
			
		||||
        error = ValidationError(
 | 
			
		||||
            detail=[
 | 
			
		||||
                ValidationError(
 | 
			
		||||
                    detail='Invalid value: %(value1)s',
 | 
			
		||||
                    params={'value1': '42'},
 | 
			
		||||
                ),
 | 
			
		||||
                ValidationError(
 | 
			
		||||
                    detail='Invalid value: %(value2)s',
 | 
			
		||||
                    params={'value2': '43'},
 | 
			
		||||
                ),
 | 
			
		||||
                'Invalid value: %(value3)s'
 | 
			
		||||
            ],
 | 
			
		||||
            params={'value3': '44'}
 | 
			
		||||
        )
 | 
			
		||||
        assert isinstance(error.detail, list)
 | 
			
		||||
        assert len(error.detail) == 3
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
        assert str(error.detail[1]) == 'Invalid value: 43'
 | 
			
		||||
        assert str(error.detail[2]) == 'Invalid value: 44'
 | 
			
		||||
 | 
			
		||||
    def test_validation_error_details_validation_errors_nested_list(self):
 | 
			
		||||
        error = ValidationError(
 | 
			
		||||
            detail=[
 | 
			
		||||
                ValidationError(
 | 
			
		||||
                    detail='Invalid value: %(value1)s',
 | 
			
		||||
                    params={'value1': '42'},
 | 
			
		||||
                ),
 | 
			
		||||
                ValidationError(
 | 
			
		||||
                    detail=[
 | 
			
		||||
                        'Invalid value: %(value2)s',
 | 
			
		||||
                        ValidationError(
 | 
			
		||||
                            detail='Invalid value: %(value3)s',
 | 
			
		||||
                            params={'value3': '44'},
 | 
			
		||||
                        )
 | 
			
		||||
                    ],
 | 
			
		||||
                    params={'value2': '43'},
 | 
			
		||||
                ),
 | 
			
		||||
                'Invalid value: %(value4)s'
 | 
			
		||||
            ],
 | 
			
		||||
            params={'value4': '45'}
 | 
			
		||||
        )
 | 
			
		||||
        assert isinstance(error.detail, list)
 | 
			
		||||
        assert len(error.detail) == 4
 | 
			
		||||
        assert str(error.detail[0]) == 'Invalid value: 42'
 | 
			
		||||
        assert str(error.detail[1]) == 'Invalid value: 43'
 | 
			
		||||
        assert str(error.detail[2]) == 'Invalid value: 44'
 | 
			
		||||
        assert str(error.detail[3]) == 'Invalid value: 45'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user