[Django] GET 시리얼라이저에서 값 처리

채린·2023년 9월 1일

역참조

related_name으로 역참조가 가능한거였다.
이름을 다르게 쓰려면 위에 source='related_name'추가하면 된다.

ex

class MyLineComSerializer(serializers.ModelSerializer):
    LineComCom=LineComComSerializer(source='linecomcom_lineCom',many=True) # 역참조 할때 필드명은 LineComCom으로 하고싶으면 필드명은 바꾸고 source쓰면 된다
    linecom_user=UserProfileSerializer() # 역참조 related_name
    class Meta:
        model=LineCom
        fields=['linecom_id','content','linecom_user','LineComCom']


SerializerMethodField

serializers.SerializerMethodField()는 사용자 정의 로직을 사용하여 값을 계산하거나 생성하는데 사용한다
def get_[필드명](self, obj): 로 필드를 만드는걸 정의할 수 있다


ex Playlist 모델 시리얼라이저에서 이 플리에 포함되는 오디오들의 포스트의 이미지들을 가져오고 싶다

class MyPliSerializer(serializers.ModelSerializer):
    img=serializers.SerializerMethodField()
    class Meta:
        model=Playlist
        fields=['playlist_id','title','des','first_audio','img']
    
    def get_img(self, playlist):
        audio_posts = playlist.playlist_audio.all()[:4].values_list('audio_post__post_image', flat=True)
        return list(audio_posts)

playlist모델의 playlist_audio필드를 다(all) 가져오고
audio_post__post_image: audio_post의 post_image필드를 list로 가져온다!
[:4]로 최대 개수를 4개로 제한

결과:

"myPlaylist:[
	{
    		"playlist_id: 1,
            "title": "새벽에 듣기 좋은 글 모음",
            "des": "내가 저장한 플리",
            "first_audio": 1,
            "img": [
            	"img url 1",
                "img url 2",
                "img url 3"
            ]
    }
]


to_representation

DRF가 Serializer 클래스 사용할 때, 직렬화된 데이터의 표현 방식을 커스터마이징(특정 필드 변경, 새로운 필드 추가) 하기 위해 to_representation 메서드를 오버라이딩하여 사용할 수 있다


ex
시리얼라이저로 Line을 부르는데, 그 중 현재 사용자가 만든 Linecom만 가져오고 싶었다
제일 윗단계에서 부르는게 Line이라 LineCom을 역참조로 가져오면 해당 Line의 모든 댓글이 와서
시리얼라이저에서 filtering했다.

Line이 하나라면 view에서 필터링해서 필요한 LineCom을 붙여주면 되는데,
Line이 many=True라서 각 Line에 대한 LineCom을 뷰에서는 어떻게 처리하는지 모르겠다.
for문을 돌려가면서 붙여주면 될거 같기도 한데, 일단은 시리얼라이저에서 처리했다.

class MyLineandComSerializer(serializers.ModelSerializer):
    linecom_line = MyLineComSerializer(many=True, read_only=True)

    class Meta:
        model = Line
        fields = ['line_id', 'content', 'linecom_line']

    def to_representation(self, instance):                          # 현재 user의 LineCom만 가져오기위해 필터링
        request = self.context.get('request')   
        user = request.user                     

        queryset = instance.linecom_line.filter(linecom_user=user)
        serializer = MyLineComSerializer(queryset, many=True, context={'request': request}) # is_my, do_like를 위해 request를 넘겨야 함(현재 사용자가 누군지 알아야 하기 때문)
        return {
            'line_id': instance.line_id,
            'content': instance.content,
            'LineCom': serializer.data
        }

또는

representation['LineCom'] = serializer.data
return representation


시리얼라이저에 request넘기기

do_like와 is_my때문에 request.user가 계속 필요하다
MyLineandComSerializer(Lines,many=True, context={'request': request})

이렇게 context={'request': request} 추가

Line도 many=True라서 뷰에서 Line과 LineCom을 어떻게 합쳐야 할지 모르겠어서,
사용자의 댓글이 있는 Line들을 넘긴 다음 시리얼라이저에서 to_representation을 사용하였다

알게된 내용:
related_name으로 역참조가 가능한거였다. 이름을 다르게 쓰려면 위에 source='related_name'추가
request를 계속해서 넘기는 방법 - do_like와 is_my때문에 request.user가 계속 필요했다

시리얼라이저에서 filtering하는법
1. to_representation
2. get_[필드명] 함수 정의하고 맨 위에는 SerializerMethodField



문제점

뷰와 시리얼라이저 둘다에서 뭔가 할수는 있으니까 둘중에 어디서 해야 효율적이고 잘쓰는건지 잘 모르겠다

0개의 댓글