이 글에서는 is_valid()
함수의 작동원리를 조사한다. 아직 미완성된 글이다.
.validate()
, .validate_<field_name>
이 언제 작동하는지 파악 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)
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
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
을 입력값과 출력값으로 가능한 것으로 본다.