to_representation

GisangLee·2022년 8월 24일
0

django

목록 보기
14/35

1. What

API의 응답 형태에 변화를 줄 수 있는 ModelSerializer 내장 메서드


2. Why to use

예를 들어 아래와 같은 테이블이 있다고 가정합시다.

  • 흡사 인스타그램 등과 같은 SNS 서비스에서 볼 거같은 테이블입니다.
  • 게시글 ( Post ) 과 게시글의 이미지 ( PostImage )들 > PostImages
    - M : N 관계

  • 게시글 ( Post )의 태그 ( Tag )들 > PostTags
    - M : N 관계

  • 이미지 ( PostImage )의 태그 ( Tag )들 > PostImageTags
    - M : N 관계

위 테이블 대로 serializer를 구성해보면 아래와 같습니다.


class TagSerializer(ModelSerializer):

    class Meta:
        model = tag_models.Tag
        fields = ("pk", "tag_name",)

class PostImageTagsSerializer(ModelSerializer):

    class Meta:
        model = tag_models.Tag
        fields = ("pk", "tag_name",)

class PostImageSerializer(ModelSerializer):

    class Meta:
        model = post_models.PostImage
        fields = ("pk", "url",)

class PostImagesSerializer(ModelSerializer):

    image = PostImageSerializer()
    tags = PostImageTagsSerializer(many=True)

    class Meta:
        model = post_models.PostImages
        fields = ("pk", "image", "tags",)

class PostSerializer(ModelSerializer):
    post_tags = TagSerializer(many=True)
    images = PostImagesSerializer(source="post_images", many=True)
        
    class Meta:
        model = post_models.Post
        fields = ("pk", "title", "post_tags", "images",)

그럼 응답은 아래와 같겠죠.

{
   "pk":1,
   "title":"즐거운 하루",
   "post_tags":[
      {
         "pk":1,
         "tag_name":"태그 이름"
      },
      {
         "pk":2,
         "tag_name":"태그 이름"
      }
   ],
   "images":[
      {
         "pk":1,
         "image":{
            "pk":1,
            "url":"이미지 주소"
         },
         "tags":[
            {
               "pk":3,
               "tag_name":"태그 이름"
            },
            {
               "pk":4,
               "tag_name":"태그 이름"
            }
         ]
      }
   ]
}

눈치 채신 분들은 아시겠지만

images에 불필요한 depth가 있다는 것을 알 수 있습니다.

   "images":[
      {
         "pk":1,
        
        
       	"""""""""""""""
        """ 여기부터 """
        
         "image":{
            "pk":1,
            "url":"이미지 주소"
         },
     
     	""" 여기까지 """
     	"""""""""""""""
     
         "tags":[
            {
               "pk":3,
               "tag_name":"태그 이름"
            },
            {
               "pk":4,
               "tag_name":"태그 이름"
            }
         ]
      }
   ]

위 형태를

아래와 같이 바꿔줄 필요가 있지요.

{
   "images":[
      {
         "pk":1,
         "url":"이미지 주소",
         "tags":[
            {
               "pk":3,
               "tag_name":"태그 이름"
            },
            {
               "pk":4,
               "tag_name":"태그 이름"
            }
         ]
      },
   ]
}

이렇게 관계로 중첩되어 있을 때 ( nested serializer)

응답의 형태를 바꿔주는 것이

to_representation 메서드입니다.


3. How to use

    def to_representation(self, instance):
        
        # 변하기 전 원래 응답 형태를 그대로 가져온다.
        representation = super().to_representation(instance)

        tag_json = {}
        image = {}
        
        # 기존 응답형태를 key, value로 루프
        for key, val in representation.items():
            
            if key == "tags":
                tag_json = val

            elif key == "image":
                tmp = {
                    **val,
                    "tags": []
                }
                image = tmp
        
        image["tags"] = tag_json
        
    	# 기존 응답 형태를 새로운 응답형태로 치환
        representation = image
        
        # 치환된 응답 형태를 반환
        return representation

위 데이터베이스와 serializer 예제 간단하게 만들어본 to_representation입니다.

대충 이렇게 사용하시면 됩니다.


profile
포폴 및 이력서 : https://gisanglee.github.io/web-porfolio/

0개의 댓글