ModelSerializer
modelSerializer는 Model에서 정의한 각 필드를 자동으로 추가해준다.
Serializer 사용시 : 필드를 하나씩 정의
class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False)
edits = EditItemSerializer(many=True) # A nested list of 'edit' items.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
ModelSerializer 사용 시 : 각 필드를 정의하는 내용을 Model(Comment)에서 정의한 것과 똑같이 쓰면서 모든 필드를 불러오고 싶다면 Meta 클래스에 '__all__'만 적어주면 된다.
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model=Comment
fields= '__all__'
fields 대신 exclude라는 속성값에 Serializer에서 제외할 필드만 작성해도 된다. 그러나 __all__이나 exclude는 권장되지 않는다. 모델의 필드가 변경되었을 때 외부로 노출하고 싶지 않은 필드까지 나타날 수 있기 때문이다.
ModelSerializer관련 알아둬야할 사항
- 각 필드에 대해서 validator를 자동으로 생성한다.
- 간단한 create, update 메서드를 자동 구현한다. ModelSerializer 소스코드에서 확인할 수 있다.
- 관계를 갖는 필드는 기본적으로 PrimaryKeyRelatedField로 매핑된다. 다만 1:N 관계에서 1 -> N 방향으로의 역방향 조회는 직접 명시하지 않으면 자동 매핑이 되지는 않는다.
- create, update시 목표하는 instance와 상관없는 필드값을 받아서 처리한다면, ModelSerializer의 data로 넘기면 안된다. ModelSerializer는 is_valid() 실행 시 instance에 포함되어있는 필드 값만 들어왔는지 검사하기 때문이다.
ModelSerializer의 옵션
depth 옵션
depth 값을 integer로 설정해주어 관계를 탐색 시 어떤 depth까지 탐색할지 지정해줄 수 있다.
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_name', 'users', 'created']
depth = 1
read_only_fields 옵션
각 필드에 read_only=True 옵션을 줘도 되지만, read_only_fields에 튜플이나 리스트로 읽기 전용 필드를 추가하여 한 번에 처리할 수도 있다. Model에서 정의한 editable=False인 필드나 AutoField는 자동으로 read_only 처리되어 따로 read_only 처리할 필요가 없다.
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_name', 'users', 'created']
read_only_fields = ['account_name']
필드에 추가로 옵션 주기 : extra_kwargs
ModelSerializer는 Model에서 정의한 필드의 옵션 설정 정보를 그대로 들고오기 때문에 추가적인 옵션 설정을 해주고 싶을 수 있다. 이때 extra_kwargs에 아래와 같이 정의하여 옵션을 추가해줄 수 있다.
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user