web-dev-qa-db-ja.com

django RESTフレームワーク:シリアライザのvalidate()メソッドからフィールドレベルのエラーを設定する

他のフィールドの値に基づいてフィールドを検証するシリアライザがあります。エラーレスポンスでは、「non_field_errors」の下にすべてを表示するのではなく、各フィールドエラーをフィールドエラーとして表示します。オブジェクトレベルの検証メソッドのValidationError。以下は私が達成しようとしていることの説明です:

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'

望ましいエラー応答は次のとおりです。

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

「BaseSerializer」セクションのドキュメントの this ページで、それを見つけました。ValidationErrorが初期化時にディクショナリ引数を取ることができることを示す例があります。

もし私がraise ValidationError({'field_val1': ['this field is not valid']})なら、欲しいJSONレスポンスが得られます。

58
Jkk.jonah

@ Jkk.jonahによる回答と同様に、これはValidationErrorを発生させますが、翻訳を再実装する必要なく元の例外テキストを再利用します。

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

デフォルト(つまり、rest_framework.fields.Fieldクラス)、利用可能なキーは次のとおりです:

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

サブクラスは独自のエラーメッセージをそこに追加できます(SerializerFieldのサブクラスです)。

ところで、新しいエラーメッセージは既存の(継承された)メッセージと自動的にマージされます-期待どおりに上書きされません。

2
frnhr

すべてのフィールドに適用されるロジックがある場合でも、次のようにすることで、望ましい結果を得ることができます。

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
1
Erick M

DRFで組み込みバリデーター(実際にはDjangoコアバリデーター)を使用している場合)は、前処理を行う必要がありますDjango ValidatorError from a function get_error_detail drfはこの目的で使用しています。

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

ValidationErrorDjangoはDjango.core.exceptionsのValidationErrorであり、ValidationErrorはrest_framework.exceptionsのValidationErrorであることに注意してください。

0
okrutny