Django customize validation error message

I have a following serializer definitions that validate request payload:

# diagnosis serializer
class ICD10Serializer(serializers.Serializer):
    icd_10 = serializers.IntegerField(required=True, allow_null=False)

class DetailsSerializer(serializers.Serializer):
    diagnosis_details = ICD10Serializer(many=True)

class ChartUpdateSerializer(serializers.Serializer):
    diagnosis = DetailsSerializer(many=True)

Its usage:

payload = ChartUpdateSerializer(data=request.data)
if not payload.is_valid():
   raise serializers.ValidationError(payload.errors)

This throws validation error message in the following format:

{
    "diagnosis": [
        {
            "diagnosisDetails": [
                {}, <- valid
                {}, <- valid
                {}, <- valid
                {}, <- valid
                {
                    "icd10": [
                        "This field may not be null."
                    ]
                }
            ]
        }
    ]
}

Here {} is also shown for valid ones. Can we simply raise validation error for invalid ones? Or better even if we can know which field and the message so custom message can be generated.

If you really need it, you can use, for example, a script like this:

def remove_empty_objects(errors, _parent_pos=None):
    def filter_empty_list_objects():
        for pos, list_value in enumerate(value, 1):
            if not list_value:
                continue

            if isinstance(list_value, ErrorDetail):
                msg = f' Init array position: {_parent_pos!r}'
                yield ErrorDetail(
                    string=str(list_value) + msg,
                    code=list_value.code,
                )
            else:
                yield remove_empty_objects(errors=list_value, _parent_pos=pos)

    for key, value in errors.items():
        if isinstance(value, list):
            errors[key] = [*filter_empty_list_objects()]
    return errors

This script will recursively go through all objects and remove empty values. I also added a message indicating the position of the object in the source array (note that here the position number starts with 1, not 0.) to get rid of the problem @willeM_ Van Onsem wrote about in the comments. But you can generally override the messages completely if you need to. I haven't tested this script extensively, but for the case you provided, it will work. Here's an example:

errors = {
    'diagnosis': [
        {'diagnosis_details': [
            {}, 
            {'icd_10': [ErrorDetail(string='This field may not be null.', code='null')]}, 
            {'icd_10': [ErrorDetail(string='This field may not be null.', code='null')]}, 
            {}, 
            {},
        ]}, 
        {'diagnosis_details': [
            {}, 
            {'icd_10': [ErrorDetail(string='This field may not be null.', code='null')]},
        ]}
    ]
}

result = remove_empty_objects(errors=errors)

{'diagnosis': [{'diagnosis_details': [{'icd_10': [ErrorDetail(string='This field may not be null. Init array position: 2', code='null')]},
                                      {'icd_10': [ErrorDetail(string='This field may not be null. Init array position: 3', code='null')]}]},
               {'diagnosis_details': [{'icd_10': [ErrorDetail(string='This field may not be null. Init array position: 2', code='null')]}]}]}
Вернуться на верх