简体   繁体   中英

Django REST Framework serializer validation

How exactly do I use validators in my serializers? I have currently create my validators in app/validators.py and have my serializers in app/serializers.py .

class OrderItemSerializer(serializers.ModelSerializer):
    item_id = serializers.IntegerField()
    item_date = serializers.DateTimeField()
    ...

    class Meta:
        model = Item
        validators = [validate_item_date]
        fields = ('item_id', 'item_date')

from rest_framework.serializers import ValidationError

validators.py

def validate_item_date(item_date):
    if item_date < {something}:
        raise ValidationError('')

My question basically: do I provide the item_date as parameter here or does it not work like this?

You can add validation to serializer like this

class OrderItemSerializer(serializers.ModelSerializer):
    def validate_item_date(self, item_date):
        if item_date < {something}:
            raise ValidationError('')
        return item_date

DRF allows for field level validation. Have your function name as: def validate_(fieldname). and drf will run that function against the corresponding field name. In the code below, "validate_item_date", drf corresponds that to the field "item_date".

class OrderItemSerializer(serializers.ModelSerializer):
    item_date = serializers.DateTimeField()

    class Meta:
        model = Item

    def validate_item_date(self, value):
        if value < 10:
            raise ValidationError('')
        return value

In your example item_date parameter in the validator function will be the validated data of the whole OrderItemSerializer ( serializer.validated_data ).

Here is how it should be:

def validate_item_date(validated_data):
    if validated_data.get('item_date') < {something}:
        raise ValidationError('')

By using serializer-lever validation you can validated against other fields of the serializer:

def validate_item_date(validated_data):
    if validated_data.get('item_date') < validated_data.get('order_attr'):
        raise ValidationError('')

Of course you should handle None values and dates comparison properly here, this is simplified version of the code.

You can use class-based validator if you want to specify {something} statically.

class OrderItemValidator:
    def __init__(self, a):
        self.a = a

    def __call__(self, value, *args, **kwargs):
        item_date = value.get('item_date')
        if item_date < self.a:
            raise serializers.ValidationError('')

class OrderItemSerializer(serializers.ModelSerializer):
    ...

    class Meta:
        validators = [OrderItemValidator(some_date)]

Be careful to not using something like that OrderItemValidator(timezone.now()) here :).

You can also specify field level validator

item_date = serializers.DateTimeField(validators=[OrderItemValidator(some_date)])

In this case this field's validated data will be passed to the validator function instead of the whole serializer's validated data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM