serializers 는 queryset과 모델 인스턴스와 같은 복잡한 데이터를 JSON, XML 또는 다른 컨텐츠 유형으로 쉽게 렌더링할 수 있는 python 기본 데이터 유형으로 변환해준다. 또한 deserialization 을 제공하여, 들어오는 데이터의 유효성을 처음 확인한 후에 구문 분석이 된 데이터를 복합 형식으로 다시 변환할 수 있다.
REST 프레임워크의 serializers 는 Django의 Form, modelForm 클래스와 매우 유사하게 작동한다. serializers 는 ModelSerializer, Serializer 클래스를 제공한다.
여기서 save()는 instance가 존재하면 update를 존재하지않으면 create를 해준다.
# .save() will create a new instance.serializer =CommentSerializer(data=data)# .save() will update the existing `comment` instance.serializer =CommentSerializer(comment, data=data)
인스턴스를 저장하는 시점에 뷰 코드가 데이터를 추가할 수 있어야하며, 이 추가 데이터에는 다른 정보가 포함될 수 있다.
>>> serializer.save(writer=request.user)
추가된 데이터는 .create() 혹은 .update()가 호출될 때 validated_data에 포함된다.
Validation
데이터를 deserializer할 때 유효성이 검증된 데이터에 접근하기 전에 is_valid() 를 호출하거나 객체 인스턴스를 저장해야한다.
>>> deserializer =CommentSerializer(data={'email':'admin@test.com', 'content':'This is test'})>>> deserializer.save()Traceback (most recent call last): File "<console>", line 1,in<module> File "/Users/jeongdaye/.pyenv/versions/restful/lib/python3.7/site-packages/rest_framework/serializers.py", line 179,in save'You must call `.is_valid()` before calling `.save()`.'AssertionError: You must call `.is_valid()` before calling `.save()`.>>> deserializer.is_valid()False>>> deserializer.errors{'created_at': [ErrorDetail(string='This field is required.', code='required')]}
만약에 is_valid()가 False라면, .errors()를 통해서 결과 오류메세지를 확인할 수 있다.
>>> deserializer.is_valid(raise_exception=True)Traceback (most recent call last): File "<console>", line 1,in<module> File "/Users/jeongdaye/.pyenv/versions/restful/lib/python3.7/site-packages/rest_framework/serializers.py", line 243,in is_validraiseValidationError(self.errors)rest_framework.exceptions.ValidationError:{'created_at': [ErrorDetail(string='This field is required.', code='required')]}
raise_exception=True 플래그를 사용해 serializers.validationError 예외를 발생시킬 수 있다.
Field 레벨 검증
validate_field
serializer 서브 클래스에 .validate_<field_name> 메소드를 추가해 custom field 유효성 검증을 지정할 수 있다.
import re emailRegex ='^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'classCommentSerializer(serializers.Serializer): email = serializers.CharField() content = serializers.CharField() created_at = serializers.DateTimeField()defvalidate_email(self,value):if(re.search(eamilRegex, value)):return valueelse:raise serializers.ValidationError("이메일 형식이 잘못되었습니다.")
ModelSerializer 클래스는 모델 필드가 포함된 Serailzer 클래스를 간단하게 만들 수 있다.
모델을 기반으로 일련의 필드가 자동으로 생성
unique_together validator 와 같은 serializer에 대한 validator를 자동 생성
.create()와 .update()의 간단한 기본 구현을 포함
from rest_framework import serializersclassCommentSerializer(serializers.ModelSerializer):classMeta: model = Comment fields = ('email','content','created_at')
만약 전체 필드를 포함하고 싶다면 __all__ 으로 속성을 설정하면된다.
from rest_framework import serializersclassCommentSerializer(serializers.ModelSerializer):classMeta: model = Comment fields ='__all__'
from rest_framework import serializersclassCommentSerializer(serializers.ModelSerializer):classMeta: model = Comment exclude = ('email','content','created')
HyperlinkedModelSerializer
HyperlinkedModelSerializer 클래스는 기본 키가 아닌 관계를 나타내기 위해 하이퍼링크를 사용한다는 점을 제외하고는 ModelSerialzer 클래스와 유사하다. 기본적으로 기본 키 필드 대신 url 필드가 포함된다.
classCommentSerializer(serializers.HyperlinkedModelSerializer):classMeta: model = Comment fields = ('url','id','email','content','created_at')
만약 상대 URL을 사용하려면 {'request': None} 을 명시적으로 전달하면된다.
/accounts/1
How hyperlinked views are determined
모델인스턴스에 하이퍼링크하기 위해 어떤 뷰를 사용했는지 알려줘야한다. 기본적으로 {model_name} -detail 스타일과 view 이름이 일치해야하며, pk 키워드 인수로 인스턴스를 찾는다. 만약 따로 지정해주고 싶다면 extra_kwargs 설정에서 view_name 또는 lookup_field 옵션을 설정하면된다.
classAccountSerializer(serializers.HyperlinkedModelSerializer):classMeta: model = Account fields = ('account_url','account_name','users','created') extra_kwargs ={'url':{'view_name':'accounts','lookup_field':'account_name'},'users':{'lookup_field':'username'}}