Serializer란?
Django에서 지원하는 내장 기능으로.
serializers.ModelSerializer를 상속받아
데이터 직렬화, 데이터 검증 등 다양한 기능 구현을 쉽게 구현 할 수 있다.
또한 제공된 메서드를 오버라이딩 하여 다양한 기능을 쉽게 구현할 수 있다.
데이터 검증
- serializer의 validate를 오버라이딩 하여
추가로 검증할 데이터를 구현할 수 있다.
이때 validation 로직은 필자는 모듈로써 관리했다.
나의 유효성 검사 모듈 관리 예시
- view 함수에서의 serializer.is_valid
if serializer.is_valid(): serializer.save(user=user) .... else: ...
- 기본적으로 검증하는 것
- 모델 필드의 최대값
- 모델 필드의 unique=True조건,
- 필수 필드를 입력하지 않았을 경우 (Null = False)
- 이미지 필드의 호환성
등등, 다양한 검증 과정이 있지만.
사용자가 추가로 검증하고 싶은 데이터가 생길 수 있다.
- 추가 데이터 검증하기
def validate(self, deliveries_data): validated_result = ValidatedData.validated_deliveries(self.context.get('user'), deliveries_data) if validated_result is not True: raise ValidationError(validated_result[1]) return deliveries_data
- validate를 오버라이딩하여 검증 과정을 커스텀 했다.
- 필자는 ValidatedData.validated_deliveries라는
커스텀 모듈을 사용하여 데이터를 검증했다.
유저 오브젝트 생성 예시
- create 메서드를 오버라이딩하여 오브젝트가 생성 될때
암호화 과정을 추가 했다.- set_password를 이용한 비밀번호 암호화
AbstractBaseUser를 상속받은 모델의 비밀번호 해싱 메서드를 호출def create(self, validated_data): user = super().create(validated_data) user.set_password(user.password) user.save() return user
- 이메일 전송 또는 포인트 적립등 개발자가 추가로 구현한 기능을
추가 할 수도 있다.# 이메일 전송 EmailService.send_email_verification_code(user, user.email, "normal") # 포인트 기본값 할당 Point.objects.create(point=29900, user_id=user.pk, point_type_id=5)
def update(self, instance, validated_data):
user = super().update(instance, validated_data)
user.set_password(user.password)
user.login_attempts_count = 0
user.save()
return user
이해하기
- super 메서드를 이용하여
부모 클래스의 메서드를 호출 및 오브젝트 생성
user.login_attempts_count = 0
와 같이 개발자가 임의의 코드를 추가하여 필드를 조정할 수 있다.
이해하기
- Serializer의 데이터 직렬화를 사용될때 호출되는 메서드
- 직렬화 과정에서 복호화가 필요한 데이터를 추가한다던지
- 또는 serializer에 구현되지 않은 추가 데이터 필드를 추가하는데 이용할 수 있다.
응용 예시 (1) : 복호화 과정
def to_representation(self, instance): information = super().to_representation(instance) decrypt_result = AESAlgorithm.decrypt_all(**information) return decrypt_result
- super() 메서드를 이용하여 부모 클래스의
to_representation를 호출하여 오브젝트 생성- 생성된 오브젝트의 데이터를 필자가 정의한 복호화 메서드에 데이터를 전송하고 전달받은 데이터를 반환했다.
응용 예시 (2) : 데이터 추가
- 사용자가 팔로우하는
- 사용자의 포인트 합산 내역 데이터 추가
def to_representation(self, instance): information = super().to_representation(instance) # 팔로우하는 판매자 데이터 추가하기 sellers = information.get('follower') seller_information = [] for pk in sellers: (...역참조를 이용한 데이터 불러오기 과정 생략..) seller_information.append(data) # 포인트 합산 내역 뽑아오기 total_plus_point = (..합산 구현 로직 생략 ..) information["total_point"] = total_point information["seller_information"] = seller_information return information
- information이라는 새로운 딕셔너리에
key값을 지정하고 value값을 대입하여 새로운 데이터를 추가했다.
사용 목적
로직 구현상 Serializer에서 제공되는 데이터 만으로는
Validation을 구현하지 못하는 경우가 있다.
따라서 APIView딴에서 Validation을 진행하게 되는데
Serializer에 추가 정보를 전달하면
Validation과정을 Serializer에서 진행할 수 있다.
호출하기
- 만약 APIView에서 Serializer에
user데이터를 전달했다면 instance를 호출할 수 있다.
- Model Serializer를 상속받은 클래스에서
self.instance를 호출할 수 있다.
사용하기
- 호출한 instance의 필드를 조회하여
데이터를 검증할 수 있도록 응용 할 수 있다.
사용 목적
로직 구현상 Serializer에서 제공되는 데이터 만으로는
Validation을 구현하지 못하는 경우가 있다.
따라서 APIView딴에서 Validation을 진행하게 되는데
Serializer에 추가 정보를 전달하면
Validation과정을 Serializer에서 진행할 수 있다.
호출하기
- serializer에서 context를 지정하여 데이터를 전달 할 수도 있다.
아래와 같이 context에 key,value쌍의 딕셔너리로 requset의 데이터를 기입한다.
- 아래 코드는 get 방식의 APIView에서 사용자가 데이터 요청을 했을 경우
어떠한 데이터에 팔로우를 했을 경우 is_like를 True로,
아니라면 False를 반환하게끔 구현된 코드이다.
- 전달받은 context의 key값 request를 호출하여
request의 user의 데이터 처리를 구현 했다.- filter 조건에 exists() 메서드를 추가한점이 보이는데
이는 데이터가 존재한다면 True를, 없다면 False를 반환한다.