이전 포스팅에서 기본적인 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를 이용할 수 있을까?
해당 고려사항에 대해서는 다음 포스팅에서 알아보도록 하자