- form 생성자 : data인자를 먼저 입력받고 뒤쪽에 instance인자를 입력받는다
- serializer 생성자 : instance인자를 먼저 입력받고 뒤쪽에 data인자를 입력받는다
Serializer 사용하는 이유
1. 데이터직렬화 사용하기위해
→ instance 인자에 모델 객체 or QuerySet 넘겨주면 된다
2. 입력값에 대한 유효성 검증 및 검증에 통과한 값들을 가져오고 DB에 저장하는 form 같은 역할
→ data 인자에 입력값 넘겨주면 된다
Serializer에 data= 인자가 주어지면
.is_valid()가 호출되고 나서야 아래의 속성에 접근할 수 있다
- .initial_data 필드
- .validated_data를 통해 유효성 검증에 통과한 값들이 .save() 시에 사용된다 c.f) form은 cleaned_data
- .errors ( 유효성 검증 수행 후에 오류 내역 )
- .data ( 유효성 검증 후에, 갱신된 인스턴스에 대한 필드값 사전 )
serializer.save(**kwargs) 호출 할 때
1. DB에 저장한 관련 instance를 리턴
2. .validated_data와 kwargs사전을 합친 데이터를
.update() / .create() 를 통해 관련 필드에 값을 할당하고, DB로의 저장을 시도
c.f) self.instance 인자를 지정했을 때 .update(), 지정하지 않았을 때 .create()
# Form
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.ip = request.META['REMOTE_ADDR']
post.save()
# Serializer
# 위의 코드를 serializer.save(**kwargs)를 통해 밑과 같이 구현할 수 있다
if serializer.is_valid():
serializer.save(author=request.user, ip=request.META['REMOTE_ADDR'])
Validators
from rest_framework.validators import ...
DRF에선 유일성 체크를 도와주는 Validators 제공
값에 대한 유효성 검사를 수행하는 호출 가능한 객체
- UniqueValidator : 1개 필드가 QuerySet 범위에서 유일성 여부 체크
- UniqueTogetherValidator : UniqueValidator의 다수 필드 버전
- BaseUniqueForValidator
- UniqueForDateValidator(BaseUniqueValidator) : 지정 날짜 범위에서 유일성 여부 체크
- UniqueForMonthValidator(BaseUniqueValidator) : 지정 월 범위에서 유일성 여부 체크
- UniqueForYearValidator(BaseUniqueValidator) : 지정 년 범위에서 유일성 여부 체크
UniqueValidator
1. 모델 필드에 unique=True 지정하면 자동 지정 ( 추천!! )
2. qeuryset ( 필수 )
message : 유효성 검사 실패 시의 에러 메세지
lookup : 디폴트 'exact'
from rest_framework.validators import UniqueValidator
class ExampleSerializer(serializers.Serializer):
...
slug = SlugField(
max_length = 100,
validators=[UniqueValidator(queryset=BlogPost.objects.all())]
)
..
UniqueForDateValidator/ UniqueForMonthValidator/ UniqueForYearValidator
queryset (필수) : 실제 대상 범위
field (필수)
data_field ( 필수) : 참조할 날짜 필드 (date, month, year)
message
→ queryset으로 전체범위 정한 후 date_field로 날짜 범위 정한 후 그 범위 내에서 필드값이 유니크한지 검사
from rest_framework.validators import UniqueForYearValidator
class ExampleSerializer(serializers.Serializer):
...
class Meta:
validators = [
UniqueForYearValidator(
queryset=BlogPostItem.objects.all()
field='slug'
date_field='published'
)
]
ValidationError
유효성 검사에 실패하면 ValidationError 예외 발생
- 장고 기본 : django.forms.exceptions.ValidationError 사용
- DRF : rest_framework.exceptions.ValidationError 사용
※ 이름은 같지만 다른 ValidationError 이므로 구분하기!
Serializer의 유효성 검사
1. 필드 정의 시에 validator 지정
2. 클래스 Meta.validators 지정
3. Field Level 검사
validate_* 라는 멤버함수 구현해서 유효성 검사 수행 c.f) form에서의 clean_* 와 유사
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate_title(self, value):
if 'django' not in value:
raise ValidationError('제목에 django가 포함돼야 한다')
return value
4. Object Level 검사
validate라는 멤버함수 구현해서 두 개 이상의 필드에 대해서 유효성 검사 수행 c.f) formd에서의 clean 과 유사
class PostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate(self, data):
if 'django' not in data['title']:
raise ValidationError('제목에 django가 포함돼야 한다')
return data
Mixins의 perform_계열 함수
APIView의 create/update/destory 멤버함수에서 실질적인 db처리 로직은
perform_create(serializer)/ perform_update(serializer)/ perform_destroy(instance)를 통해 이루어진다
class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def perform_create(self, serializer):
# 인증이 되어있다는 가정
author = self.request.user
ip = self.request.META['REMOTE_ADDR']
serializer.save(author=author, ip=ip)
위와 같은 방법으로 주로 사용한다