Serializer를 만들 때, 각 필드를 하나하나 정의해 주었다. 마치 모델을 다시 한 번 작성하는 것 같은 불편함이 있었다. 이 문제를 해결해 주는 것이 ModelSerializer이다.
ModelSerializer는 크게 3가지 기능을 제공
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = 모델명
fields = ['id', 'name']
class Meta 옵션
필수작성
fields = ['id', 'name'] 직접명시
fields = '__all__' 전체 필드 가져옴
serializer로 정의해 줘야 되는 필드
Example
User 객체의 모델에는 full_name 필드만 있다고 가정 여기서 이름만 뽑아내서 JSON에 first_name을 추가
# Serializer된 User객체
"id" : 1,
"full_name": '{"first_name": "soms", "last_name": "kim"}',
JSON에는 full_name 필드에 해당하는 객체의 "full_name" 속성만 포함된다.
기본적으로 객체를 시리얼라이저를 통해 JSON으로 직렬화할 때
model 에 정의된 필드는 Serializer 클래스 안의 Meta 클래스(
class Meta:
model = MODEL클래스이름
...
)에서 model = MODEL클래스이름 만 추가하면 자동으로 시리얼라이저 필드로 추가되지만
모델에 last_name 필드가 없어서 시리얼라이저 필드에 추가할 수가 없기 때문이다.
class UserSerializer(serializers.Serializer):
full_name = JSONField
last_name = serializers.SerializerMethodField() # 1. 필드 추가
class Meta:
model = User
def get_first_name(self, obj): # 2. 메소드 추가. 이 메소드는 객체를 인자로 받고
return obj.full_name['first_name'] # 객체의 full_name 속성 값에서 'last_name' 키 값을 리턴
SerializerMethodField 를 사용하면 객체의 모델에 first_name필드가 없음에도 불구하고 JSON에 first_name 속성도 포함할 수 있다.
"id" : 1,
"full_name": '{"first_name": "soms", "last_name": "kim"}',
"first_name : "soms"
Nested Relationships
ForeignKey 필드를 사용하고자 할 때, 기본적으로 아무런 설정이 없으면 참조하고 있는 pk 값을 가져온다. 만약 pk 값 외에 다른 값을 가져오고 싶다면, 아래와 같은 메소드를 이용할 수 있다.
1) String of related object / StringRelatedField Tutorial
class ArticleSerializer(serializers.ModelSerializer):
...
author = serializers.StringRelatedField()
API 호출 결과
models.py
class Journalist(models.Model):
...
def __str__(self):
return f"{ self.first_name } { self.last_name }"
2) All information of related object
class JournalistSerializer(serializers.ModelSerializer):
...
# articles = ArticleSerializer(many=True, read_only=True)
class ArticleSerializer(serializers.ModelSerializer):
...
author = JounalistSerializer(read_only=True)
API 호출 결과
이 필드는 Read only로만 사용된다. 비슷한 역할을 하는 모듈로 PrimaryKeyRelatedField가 있는데, 이 모듈은 타겟 모델의 primary key 값을 가져오게 된다.
Links of related object / HyperlinkedRelatedField()
[serilaizers.py]
class JournalistSerializer(serializers.ModelSerializer):
...
articles = serializers.HyperlinkedRelatedField(many=True,
read_only=True, view_name="article-detail")
[views.py]
class JournalistListCreateAPIView(APIView):
def get(self, request):
journalists = Journalist.objects.all()
serializer = JournalistSerializer(journalists, many=True,
context={'request': request})
return Response(serializer.data)
참고
https://www.django-rest-framework.org/api-guide/serializers/#including-extra-context
https://velog.io/@jcinsh/DRF-5-ModelSerializer
https://velog.io/@phyyou/DRF-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B0-6-ModelSerializer