web-dev-qa-db-fra.com

cadre de repos django: définition d'une erreur au niveau du champ à partir de la méthode serializer validate ()

J'ai un sérialiseur qui valide les champs en fonction des valeurs des autres champs. Dans la réponse d'erreur, j'aimerais afficher chaque erreur de champ comme une erreur de champ plutôt que de tout afficher sous "non_field_errors", ce qui se produirait si je levais une ValidationError dans la méthode validate au niveau de l'objet. Vous trouverez ci-dessous une illustration de ce que j'essaie de réaliser:

MySerializer(ModelSerializer):
    ...
    def validate(self, data):
        field_val1 = data['field_val1']
        field_val2 = data['field_val2']
        if not self._is_field_valid(field_val1, field_val2):
            # The below line is how I would do what I want with Django
            # Forms, however, it's not valid in DRF
            self._errors['field_val1'] = 'this field is not valid'

La réponse d'erreur souhaitée est:

{'field_val1': ['this field is not valid']}
23
Jkk.jonah

Je l'ai compris, sur this page de la documentation dans la section "BaseSerializer", un exemple montre que ValidationError peut prendre un argument de dictionnaire lors de l'initialisation. 

Si j'ai raise ValidationError({'field_val1': ['this field is not valid']}) j'obtiens la réponse JSON souhaitée.

40
Jkk.jonah

Comme pour la réponse de @ Jkk.jonah, ceci soulève une ValidationError, mais il réutilise le texte de l'exception d'origine sans qu'il soit nécessaire de réimplémenter les traductions:

try:
    serializer.fields['field_val1'].fail('required')
except ValidationError as exc:
    raise ValidationError({
        'field_val1': exc.detail,
    })

Par défaut (c'est-à-dire sur la classe rest_framework.fields.Field), les clés disponibles sont les suivantes:

default_error_messages = {
    'required': _('This field is required.'),
    'null': _('This field may not be null.')
}

Les sous-classes peuvent y ajouter leurs propres messages d'erreur (et Serializer est une sous-classe de Field). 

En passant, les nouveaux messages d’erreur seront automatiquement fusionnés avec les messages (Hérités) existants - ne seront pas remplacés comme prévu.

1
frnhr

Si vous avez une logique qui s'applique à tous les champs, vous pouvez toujours obtenir le résultat souhaité en procédant comme suit:

def validate(self, data):
    for key, value in data.items():
        # checks if value is empty
        if not value:
            raise serializers.ValidationError({key: "This field should not be left empty."})

    return data
0
Erick M

Si vous utilisez des validateurs intégrés à DRF (qui sont en fait des validateurs principaux de Django), vous devez pré-traiter Django ValidationError provenant du validateur avec une fonction que get_error_detail drf utilise à cette fin. 

def _validate_min_value(self, data, key): try: MinValueValidator(Decimal('0.01'))(data.get(key)) except ValidationErrorDjango as exc: raise ValidationError( {key: get_error_detail(exc)} )

Notez que ValidationErrorDjango est une ValidationError de Django.core.exceptions, alors que ValidationError est une de rest_framework.exceptions

0
okrutny