이전 포스팅에서 기본적인 Serializers에 대해 알아보았다.
오늘은serializer에 새로운field를 추가해보록 하자.
SerializerMethodField를 이용하면serializer에 임의로 원하는field를 추가할 수 있다. (이미 존재하는field를 변경할 수도 있다.)
📌 예시
유저 정보 조회 시 유저가 작성한 게시글의 개수를 포함시켜보자.
1) serializer 수정
post_count라는 필드를SerializerMethodField로 선언하고get_을 붙여서get_post_count라는 함수로 해당 필드가 어떤 값을 반환하는지 정의한다.get_post_count함수에서obj는serialzer에 넣은UserModel이다.# user/serializers.py from rest_framework import serializers from user.models import User as UserModel class UserModelSerializer(serializers.ModelSerializer): """ 유저 모델 Serializer """ post_count = serializers.SerializerMethodField() def get_post_count(self, obj): post_count = obj.post_set.all().count() return post_count class Meta: model = UserModel fields = ['id', 'email', 'username', 'password', 'post_count'] extra_kwargs = { 'password': {'write_only': True} }
2) 응답 데이터 확인
ForeignKey를 가지고있는 경우 해당 모델의serializer를field로 포함시킬 수 있다.
📌 예시
게시글이
ForeignKey로 가지고 있는 유저(작성자)의 정보를 나타내보자.1) Default
기본적으로
ForeignKey는 DB에id값으로 저장되기 때문에 그대로id로 표현된다.
serailzer정의# post/serializers.py from rest_framework import serializers from post.models import Post as PostModel class PostModelSerializer(serializers.ModelSerializer): class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date"]
view정의# posts/views.py from rest_framework import status, exceptions from rest_framework.views import APIView from rest_framework.response import Response from post.models import Post as PostModel from post.serializers import PostModelSerializer # 게시글 View class PostView(APIView): # 게시글 상세 조회 def get(self, request, post_id): post_obj = PostModel.objects.get(id=post_id) post_info = PostModelSerializer(post_obj).data return Response(post_info, status=status.HTTP_200_OK)
- 응답 데이터
2) SerializerMethodField
앞서 알아본 것처럼
SerializerMethodField를 이용해서 임의로 설정할 수도 있다.
serailzer정의
:user필드를username으로 표현해보자# posts/serializers.py from rest_framework import serializers from post.models import Post as PostModel class PostModelSerializer(serializers.ModelSerializer): user = serializers.SerializerMethodField() def get_user(self, obj): return obj.user.username class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date"]
- 응답 데이터
3) Serializer
ForeignKey에 해당하는 모델의serializer로 표현할 수 있다.
serailzer정의
:user필드를 앞서 정의한UserModelSerializer를 이용해서 나타내보자.from rest_framework import serializers from post.models import Post as PostModel from user.serializers import UserModelSerializer class PostModelSerializer(serializers.ModelSerializer): user = UserModelSerializer() class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date"]응답 데이터
💡 게시글 조회 시
UserModelSerializer로 표현한 유저정보와 유저 정보 조회시UserModelSerializer로 표현한 정보가 같은 것을 확인해보자.
지금까지는
SerializerMethodField나ForeinKey의 정보를 조회할 경우에 대해서 알아보았다.
그렇다면 모델을 생성할 때는SerializerMethodField나ForeinKey를 어떻게 표현해야할까?
SerializerMethodField는 모델을 생성할 때(DB에 데이터를 저장할 때) 필요없는 정보이므로 신경쓰지않아도 된다. 즉, 무시한다.
하지만ForeinKey처럼 이미 존재하는field를SerializerMethodField로 표현한다면 해당 정보를 따로 넣어줘야한다.
📌 예시
게시글
serialzer에temp라는 필드와user필드를SerializerMethodField로 나타냈을 경우, 게시글 생성 시
serialzer정의
temp필드는 임의로 만든 필드
user필드는ForeinKey인 유저의 정보를username으로만 표현# posts/serializers.py from rest_framework import serializers from post.models import Post as PostModel class PostModelSerializer(serializers.ModelSerializer): temp = serializers.SerializerMethodField() user = serializers.SerializerMethodField() def get_temp(self, obj): return "This is SerializerMethodField" def get_user(self, obj): return obj.user.username class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date", "temp"]
view정의
temp는 DB에 저장할 때 필요없지만user는 필요하기 때문에request.user로 유저 정보를 받아서 넣어준다.# post/views.py # 게시글 View class PostView(APIView): # 게시글 생성 def post(self, request): user = request.user post_info = request.data serializer = PostModelSerializer(data=post_info) if serializer.is_valid(): serializer.save(user=user) # 유저 정보를 넣어준다 return Response(serializer.data, status=status.HTTP_200_OK) return Response({"error" : "게시글 생성 실패"}, status=status.HTTP_400_BAD_REQUEST)
- 요청/응답 데이터
ForeignKey는 모델 생성시 어떻게 해야할지 알아보자2-1) Default
기본적으로
ForeignKey는 DB에id값으로 저장되기 때문에 그대로id로 표현되었다. 따라서 모델 생성시에도id값으로 넣어주면 된다.
serializer정의# post/serializers.py from rest_framework import serializers from post.models import Post as PostModel class PostModelSerializer(serializers.ModelSerializer): class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date"]
view정의# post/views.py # 게시글 View class PostView(APIView): # 게시글 생성 def post(self, request): post_info = request.data # user 정보도 request.data에 포함되어 있다. serializer = PostModelSerializer(data=post_info) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response({"error" : "게시글 생성 실패"}, status=status.HTTP_400_BAD_REQUEST)
- 요청/응답 데이터
2-2) SerializerMethodField
ForeignKey를SerializerMethodField로 표현한 경우는 앞에서 알아봤기 때문에 넘어가도록 한다.
2-3) Serializer
ForeignKey에 해당하는 모델의 serializer로 표현한 경우, 해당 모델을 생성할 때에는ForeignKey의serialier에read_only=True속성을 넣어주고,SerializerMethodField때와 같이ForeignKey정보를 따로 넣어줘야한다.
serializer정의# post/serializers.py class PostModelSerializer(serializers.ModelSerializer): user = UserModelSerializer(read_only=True) # read_only=True class Meta: model = PostModel fields = ["id", "title", "content", "user", "views", "is_active", "created_date"]
view정의# post/views.py # 게시글 View class PostView(APIView): # 게시글 생성 def post(self, request): user = request.user post_info = request.data serializer = PostModelSerializer(data=post_info) if serializer.is_valid(raise_exception=True): serializer.save(user=user) # 유저 정보를 따로 넣어준다. return Response(serializer.data, status=status.HTTP_200_OK) return Response({"error" : "게시글 생성 실패"}, status=status.HTTP_400_BAD_REQUEST)
- 요청/응답 데이터
- 유저 정보 조회 시 유저 객체 데이터가 가진 속성 이외의 정보도 알고 싶다면 어떻게해야할까?
ex) 유저가 가진 게시글 개수:
SerializerMethodField를 이용한다
- 유저 생성 시 유저 정보가 유효한지 어떻게 검증할까?
ex) 유저 아이디가 겹칠 경우 에러 발생 시
- 유저 생성 시 비밀번호는 어떻게 해시할까?
- 현재 비밀번호는 문자열 그대로 저장되고 있지만 보안상 해시할 필요가 있다.
- 유저 정보를 수정하고 싶을 때도 Serializers를 이용할 수 있을까?
해당 고려사항에 대해서는 다음 포스팅에서 알아보도록 하자