is_valid()

succeeding·2022년 4월 7일
0

이 글에서는 is_valid()함수의 작동원리를 조사한다. 아직 미완성된 글이다.

목표

  1. Serializer 클래스에서 커스터마이징한 .validate(), .validate_<field_name>이 언제 작동하는지 파악
  2. serliazers.ValidationError가 정확히 언제 발생하는지 알기 위해서.

예상

호출되는 메서드가 다양해서 아직 모든 내용을 살펴보진 않았지만 현재까지 살펴본 내용을 바탕으로 각 목적에 대한 답을 짐작해본다.
1. 아직 모르겠다.
2. is_valid()가 호출하는 다양한 메서드 중 ValidationError를 호출하는 것들도 있고 없기도 한데, 상위 메서드에서 예외처리를 하여 에러 메시지를 담고 계속 코드가 진행 되게끔 한다. 결국 is_valid()가 최종적으로 예외처리를 마무리 짓고 오류 코드를 리턴한다.

함수의 작동 순서

BaseSerializer.is_valid

    def is_valid(self, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )

        if not hasattr(self, '_validated_data'):
            try:
            # 1.
	            self._validated_data = self.run_validation(self.initial_data)
                
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)

1. Serializer.run_validation

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        # 1-1.
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
		
        value = self.to_internal_value(data)
        try:
            self.run_validators(value)
            value = self.validate(value)
            assert value is not None, '.validate() should return the validated data'
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))

        return value
1-1. Field.validate_empty_values(self, data)
def validate_empty_values(self, data):
        """
        Validate empty values, and either:

        * Raise `ValidationError`, indicating invalid data.
        * Raise `SkipField`, indicating that the field should be ignored.
        * Return (True, data), indicating an empty value that should be
          returned without any further validation being applied.
        * Return (False, data), indicating a non-empty value, that should
          have validation applied as normal.
        """
        if self.read_only:	# Serializer에서 필드별로 설정하는 그 read_only가 맞다. 
            return (True, self.get_default())

        if data is empty:
            if getattr(self.root, 'partial', False):
                raise SkipField()
            if self.required:
                self.fail('required')
            return (True, self.get_default())

        if data is None:
            if not self.allow_null:
                self.fail('null')
            # Nullable `source='*'` fields should not be skipped when its named
            # field is given a null value. This is because `source='*'` means
            # the field is passed the entire object, which is not null.
            elif self.source == '*':
                return (False, None)
            return (True, None)

        return (False, data)

class empty

class empty:
    """
    This class is used to represent no data being provided for a given input
    or output value.

    It is required because `None` may be a valid input or output value.
    """
    pass

입력값이 없는 경우를 나타내는 클래스이다. 이를 통해 값이 없다는 null과 입력이 없다는 것을 구분하며 null을 입력값과 출력값으로 가능한 것으로 본다.

0개의 댓글