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']
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"
]
}
]
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
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
뷰와 시리얼라이저 둘다에서 뭔가 할수는 있으니까 둘중에 어디서 해야 효율적이고 잘쓰는건지 잘 모르겠다