Какие типы проверок автоматически обрабатываются Django Rest Framework? - PullRequest
0 голосов
/ 08 ноября 2018

Допустим, у меня есть модель, определенная следующим образом:

from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator

alphanumeric_validator = RegexValidator(r'^[a-zA-Z0-9]*$', 'Only alphanumeric characters are allowed.')

class Person(model.Model):
    name = models.CharField(max_length=60, validators=[alphanumeric_validator])
    number = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100)])
    email = models.EmailField()

Теперь, допустим, я сериализую и создаю объекты Person с использованием Django Rest Framework.Это выглядит так:

from rest_framework import serializers
from .models import Person
from rest_framework.response import Response

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = ('name', 'number', 'email')

class PostPerson(APIView):
    def post(self, request, format=None):
        serializer = PersonSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()=
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Теперь мой вопрос таков: когда я проверяю сериализатор, используя is_valid(), обрабатывает ли DRF validators=[alphanumeric_validator] и validators=[MinValueValidator(0), MaxValueValidator(100)]?Кроме того, я уверен, что DRF автоматически обрабатывает свойство max_length, но также проверяет, является ли email действительным адресом электронной почты, используя правильное регулярное выражение?

Меня, как правило, просто смущают чистота, full_clean и все методы, которые вызываются во время проверок форм и сериализаций, поэтому я хотел бы получить некоторые убедительные объяснения.

Заранее спасибо.

1 Ответ

0 голосов
/ 08 ноября 2018

валидация структуры отдыха Django ведет себя аналогично валидации Django ModelForm; он принимает аргументы из ваших полей моделей и соответственно проверяет.

Например, мы возьмем простой класс модель и сериализатор, который имеет поле с ограничением уникальности.

class CustomerReportRecord(models.Model):
    time_raised = models.DateTimeField(default=timezone.now, editable=False)
    reference = models.CharField(unique=True, max_length=20)


class CustomerReportSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomerReportRecord

и когда мы открываем оболочку Django, мы видим, что валидатор был применен к сериализатору (обратите внимание на max_length и список validators)

>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
    id = IntegerField(label='ID', read_only=True)
    time_raised = DateTimeField(read_only=True)
    reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])

Печать repr экземпляра сериализатора покажет вам, какие именно правила проверки он применяет. Для экземпляра модели не вызывается никаких дополнительных скрытых действий проверки.

Когда дело доходит до методов .clean и .full_clean, это просто еще один способ проверки введенных пользователем данных - нормализация их до согласованного формата. Они выполняются в формах Django, когда вы вызываете метод .is_valid() в форме , а не в сериализаторе структуры остальных.

Вернемся к валидаторам REST framework. Давайте рассмотрим метод Serializer.to_internal_value.

def to_internal_value(self, data):
    """
    Dict of native values <- Dict of primitive datatypes.
    """
    if not isinstance(data, dict):
        message = self.error_messages['invalid'].format(
            datatype=type(data).__name__
        )
        raise ValidationError({
            api_settings.NON_FIELD_ERRORS_KEY: [message]
        })

    ret = OrderedDict()
    errors = OrderedDict()
    fields = self._writable_fields

    for field in fields:
        validate_method = getattr(self, 'validate_' + field.field_name, None)
        primitive_value = field.get_value(data)
        try:
            validated_value = field.run_validation(primitive_value)
            if validate_method is not None:
                validated_value = validate_method(validated_value)
        except ValidationError as exc:
            errors[field.field_name] = exc.detail
        except DjangoValidationError as exc:
            errors[field.field_name] = list(exc.messages)
        except SkipField:
            pass
        else:
            set_value(ret, field.source_attrs, validated_value)

    if errors:
        raise ValidationError(errors)

    return ret

Здесь мы видим, что сериализатор вызывает метод field.run_validation, который использует валидаторы поля модели и выдает DjangoValidationError, если проверка не удалась. Если это удастся, он продолжит запускать любые дополнительные валидаторы, такие как валидаторы, специфичные для полей сериализатора (.validate_<field_name>).

Подробнее о проверке и о том, как она работает в Django & DRF, читайте здесь:

  1. Проверка поля формы Django 2.1
  2. Валидаторы - документы DRF
  3. Проверка сериализатора - документы DRF
  4. Правильный способ проверки моделей Django
  5. Код сериализатора DRF

Надеюсь, это поможет понять, как валидация работает в DRF, хотя бы немного

РЕДАКТИРОВАТЬ: Пока ваша область, в которой вы храните электронную почту, определена как EmailField в ваших моделях, тогда DRF будет проверять электронную почту. Подробнее об этом можно узнать здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...