wake-up-neo.net

django Rest Framework: Festlegen des Feldebenenfehlers von der validate () - Methode des Serialisierers

Ich habe einen Serialisierer, der Felder anhand der Werte anderer Felder überprüft. In der Fehlerantwort möchte ich jeden Feldfehler als Feldfehler anzeigen, anstatt alles unter "non_field_errors" anzuzeigen, was passieren würde, wenn ich erhöhen würde ein ValidationError in der Validate-Methode auf Objektebene. Im Folgenden wird veranschaulicht, was ich erreichen möchte:

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'

Die gewünschte Fehlerantwort ist:

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

Ich habe es herausgefunden, auf dieser Seite der Dokumentation im Abschnitt "BaseSerializer". Es gibt ein Beispiel, das zeigt, dass ValidationError bei der Initialisierung ein Wörterbuchargument annehmen kann. 

Wenn ich raise ValidationError({'field_val1': ['this field is not valid']}) bin, erhalte ich die gewünschte JSON-Antwort.

40
Jkk.jonah

Ähnlich wie bei der Antwort von @ Jkk.jonah wird eine ValidationError erzeugt, der ursprüngliche Ausnahmetext wird jedoch wiederverwendet, ohne dass Übersetzungen neu implementiert werden müssen:

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

Standardmäßig (d. H. Für die Klasse rest_framework.fields.Field) stehen folgende Schlüssel zur Verfügung:

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

Unterklassen können dort eigene Fehlermeldungen hinzufügen (und Serializer ist eine Unterklasse von Field). 

Übrigens, neue Fehlermeldungen werden automatisch mit vorhandenen (Vererbten) Nachrichten zusammengeführt - nicht wie erwartet überschrieben.

1
frnhr

Wenn Sie über eine Logik verfügen, die für alle Felder gilt, können Sie trotzdem das gewünschte Ergebnis erhalten, indem Sie Folgendes tun:

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

Wenn Sie in DRF integrierte Validatoren verwenden (die eigentlich Django-Core-Validatoren sind), müssen Sie den Django ValidationError, der vom Validator kommt, mit einer Funktion get_error_detail drf vorverarbeiten. 

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)} )

Beachten Sie, dass ValidationErrorDjango ein ValidationError von Django.core.exceptions ist, während ValidationError eine von rest_framework.exceptions ist.

0
okrutny