본문 바로가기
Django/Django Rest Framework

15. Django DRF serializer

by S.T.Lee 2022. 6. 19.

사용 방법

app에 serializers.py 파일을 만들어준다.

from rest_framework import serializers

class UserSErializer(serializers.ModelSerializer):
    class Meta:
        model = ""
        fields = ""

이때 Meta가 가장 중요하다. model과 field는 꼭 선언해줘야한다.

선언된 model에 지정된 field의 내용을 serializer가 json 형식으로 알려준다.

#serializers.py
from rest_framework import serializers
from user.models import User as UserModel

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = '__all__'
#views.py
from user.serializers import UserSerializer

class UserView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    def get(self, request):
        user = request.user
        #data를 붙여야 json 형식으로 입력 받을 수 있다.
        return Response(UserSerializer(user).data)

결과물

위와 같이 비밀번호도 보임으로 저런 민감 정보는 없애고 하는게 일반적이다.

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = ['username', 'email', 'fullname', 'join_date']

단, class안의 object 또는 역참조만 작성 가능하다. 하단의 경우 역참조인 userprofile을 불러왔는데 id값을 보여주는걸 볼수 있다.

from rest_framework import serializers
from user.models import User as UserModel
from user.models import UserProfile as UserProfileModel

class UserProfileSerialzer(serializers.ModelSerializer):
    class Meta:
        model = UserProfileModel
        fields = ['introduction', 'birthday', 'age']

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = ['username', 'email', 'fullname', 'join_date', 'userprofile']

우리가 필요한건 userprofile의 세부내용인데 이때는 하단과 같이 선언해주면 된다.

from rest_framework import serializers
from user.models import User as UserModel
from user.models import UserProfile as UserProfileModel
from user.models import Hobby as HobbyModel

class UserProfileSerialzer(serializers.ModelSerializer):
    class Meta:
        model = UserProfileModel
        fields = ['introduction', 'birthday', 'age']

class UserSerializer(serializers.ModelSerializer):
    userprofile = UserProfileSerialzer()
    class Meta:
        model = UserModel
        fields = ['username', 'email', 'fullname', 'join_date', 'userprofile']

중요한건 Meta 밖에서 선언해줘야 읽는다는 점이다.

 

object, queryset의 차이점

from rest_framework import serializers
from user.models import Hobby, User as UserModel
from user.models import UserProfile as UserProfileModel
from user.models import Hobby as HobbyModel

class HobbySerializer(serializers.ModelSerializer):
    class Meta:
        model = HobbyModel
        fields = ['name']

class UserProfileSerialzer(serializers.ModelSerializer):
    hobby = HobbySerializer()
    class Meta:
        model = UserProfileModel
        fields = ['introduction', 'birthday', 'age', 'hobby']

class UserSerializer(serializers.ModelSerializer):
    userprofile = UserProfileSerialzer()
    class Meta:
        model = UserModel
        fields = ['username', 'email', 'fullname', 'join_date', 'userprofile']

위의 코드로 실행할시 위의 사진과 같은 결과가 나오는걸 확인할 수 있다. 왜 null이 나오는 것일까?

이유는 UserProfileSerializer의 경우 OneToOneField여서 무조건 object으로 주고 HobbySerializer의 경우 ManyToManyField여서 QuerySet으로 주기 떄문이다.

 

따라서 하단과 같이 코드를 작성해줘야한다.

hobby = HobbySerializer(many=True)

취미가 같은 사람만 목록에서 빼오기

class HobbySerializer(serializers.ModelSerializer):
    same_hobby_users = serializers.SerializerMethodField()
    def get_same_hobby_users(self, obj):
        return "Test!"
    class Meta:
        model = HobbyModel
        fields = ['name', 'same_hobby_users']

취미가 같은 사람이 빼오기 위해서 serializers.SerializerMethodField()를 사용할것이다.

이때 set_hobby_users와 같이 새로운 변수를 설정해주면 무조건 get_ 변수명(self, obj) 함수를 만들어줘야한다.

obj는 model의 object가 나온다. 이때는 Hobby의 object가 출력된다.

class HobbySerializer(serializers.ModelSerializer):
    same_hobby_users = serializers.SerializerMethodField()
    def get_same_hobby_users(self, obj):
        user_list = []
        for user_profile in obj.userprofile_set.all():
            user_list.append(user_profile.user.username)
        return user_list
    class Meta:
        model = HobbyModel
        fields = ['name', 'same_hobby_users']
        
        
#물론 이거를
class HobbySerializer(serializers.ModelSerializer):
    class Meta:
        model = HobbyModel
        fields = ['name', 'userprofile_set']
#으로 바로 들어갈 수 있다. 물론 가공을 해야겠지만.

exclude를 안해줘서 자기자신도 포함되서 나왔다

 

이름 바꾸기

class UserSerializer(serializers.ModelSerializer):
    userprofile = UserProfileSerialzer()
    #userprofile를 user_detail로 바꾸고 싶으면
    user_detail = UserProfileSerialzer(source="userprofile")
    class Meta:
        model = UserModel
        fields = ['username', 'email', 'fullname', 'join_date', 'user_detail']

 

 

list comprehension

class HobbySerializer(serializers.ModelSerializer):
    same_hobby_users = serializers.SerializerMethodField()
    def get_same_hobby_users(self, obj):
        user_list = []
        for user_profile in obj.userprofile_set.all():
            user_list.append(user_profile.user.username)
        return user_list
	#바꾸면
    def get_same_hobby_users(self, obj):
    	return [user_profile.user.username for user_profile in obj.userprofile_set.all()]