Serializer

teal·2025년 3월 20일
0

Django

목록 보기
5/5

serializer

django에서 API 등을 만들다 보면 serializer는 필수불가결한 존재이다. 사용하다보면 validate를 재정의해서 사용하기도 하고 validate_{field_name}, to_representation 등을 재정의해서 사용하곤 한다.

그런데 serializer의 각 메소드들은 언제 호출되고 어떤 용도로 사용되는 걸까?

먼저 create, update와 같이 입력 데이터를 검증하고 처리하는 경우에는 다음과 같다.

is_valid

시리얼라이저 객체가 생성되고 나서 가장 먼저 호출하는 함수는 is_valid이다.

    def is_valid(self, *, raise_exception=False):
        # This implementation is the same as the default,
        # except that we use lists, rather than dicts, as the empty case.
        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:
                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)

내부 구조는 다음과 같으며 _validated_data가 존재하지 않을 시 즉, validation이 수행되지 않았으면 initial_data를 기준으로 run_validation를 수행한다.

run_validation

    def run_validation(self, data=empty):
        ...
        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

    def to_internal_value(self, data):
        ...
        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] = get_error_detail(exc)
            except SkipField:
                pass
            else:
                set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise ValidationError(errors)

        return ret

위의 코드에서 tointernal_value가 수행되며 각 필드에 대해서 run_validation을 수행하고 만약 시리얼라이저에 validate{field_name}이 정의되어 있을 경우 이를 수행하고 에러 발생시 errors에 담는다.

이때 각 필드의 run_validation 호출 시 run_validator가 호출되며 각 필드에 정의된 validator를 수행한다.

이 과정이 끝나면 run_validation 마지막에 validate가 호출되고 모든 검증, 변형이 끝난 결과값이 반환되고 이를 validated_data에서 확인할 수 있다.

to_internal_value

클라이언트에서 받은 데이터를 필드로 변환하는 작업을 수행한다.

validate_{field_name}

특정 필드에 대해서만 검증을 수행할때 정의해서 사용한다. 정의된 validator가 수행되고 호출된다.

validate

대부분의 과정이 끝나고 마지막에 수행되는 검증 함수이다. 객체 전체에 대한 검증이나 여러 필드가 상호작용할 때의 검증 시 사용한다.

to_representation

data(property 함수) 호출 시 호출되는 함수로 출력 시점에 데이터를 가공할 때 사용한다.

save

save 함수 호출시 인스턴스의 여부, 즉 생성인지 업데이트인지에 따라서 create, update가 각각 호출된다.

일반 시리얼라이저엔 create, update가 정의되어 있지 않고 ModelSerailizer에는 정의되어 있다

data

data 호출 시 initial_data, _validated_data로 현재 단순 직렬화인지, 생성, 수정인지 파악 후 둘다 없을 경우 단순 직렬화로 판단하고 둘다 존재할 경우 is_valid가 끝난 상태로 파악한다. 만약 _validated_data만 없는 경우 is_valid를 먼저 하라는 에러를 발생시킨다.

profile
고양이를 키우는 백엔드 개발자

0개의 댓글