-
[Django]쿼리 최적화(GroupConcat->select_related().prefetch_related()/Dto 공부)카테고리 없음 2023. 7. 26. 21:26
story_place_subquery = Story.objects.filter(id=story_id).values('place') same_place_story = Story.objects.filter(place=Subquery(story_place_subquery)).exclude(id=story_id).annotate( place_name=F('place__place_name'), writer_is_verified=F('writer__is_verified'), nickname=F('writer__nickname'), extra_pics=GroupConcat('photos__image')) for story in same_place_story: story.rep_pic = story.rep_pic.url if story.extra_pics is not None: story.extra_pics = map( append_media_url, story.extra_pics.split(',')[:3]) return same_place_story
story_place_subquery = Story.objects.filter( id=story_id ).values('place') same_place_story = Story.objects.filter(place=Subquery(story_place_subquery)).select_related( 'writer', 'place' ).prefetch_related( 'photos' ).exclude(id=story_id) same_place_story_dto = StoryDto( id = same_place_story.id, title = same_place_story.title, preview=same_place_story.preview, rep_pic=same_place_story.rep_pic.image.url, extra_pics=[photo.image.url for photo in same_place_story.photos.all()], place_name=same_place_story.place.place_name, writer_is_verified=same_place_story.writer.writer_is_verified, nickname= same_place_story.writer.nickname, created=same_place_story.created, story_review=None, html_content=None, tag=None, views=None, story_like=None, like_cnt=None, comment_cnt=None, category=None, semi_category=None, writer=None, profile=None, map_image=None, writer_is_followed=None, )
same_place_story는 쿼리셋이므로 직접 id, title, preview 등과 같이 속성에 접근할 수 없습니다. 대신 same_place_story는 여러 개의 객체를 담고 있는 쿼리셋이므로, 이를 순회하면서 각 객체에 대한 정보를 StoryDto 객체로 변환하여 리스트에 추가해야 합니다.
또한, rep_pic, extra_pics, place_name, writer_is_verified, nickname, created 등의 정보는 쿼리셋 내부에서 다룰 수 있으며, 더 이상 Subquery를 사용할 필요가 없습니다. 이 정보들은 select_related와 prefetch_related를 사용하여 이미 미리 로드되었습니다.
class SamePlaceStorySelector: def __init__(self, user:User): self.user = user def list(self, story_id: int): story_place_subquery = Story.objects.filter(id=story_id).values('place') same_place_stories = Story.objects.filter(place=Subquery(story_place_subquery)).select_related('writer', 'place').prefetch_related('photos').exclude(id=story_id) story_dtos = [] for story in same_place_stories: extra_pics = [photo.image.url for photo in story.photos.all()[:3]] story_dto = StoryDto( id=story.id, title=story.title, place_name=story.place.place_name, story_review=None, preview=story.preview, html_content=None, tag=None, views=None, story_like=None, like_cnt=None, comment_cnt=None, category=None, semi_category=None, writer=story.writer, writer_is_verified=story.writer.is_verified, nickname=story.writer.nickname, profile=None, created=story.created, map_image=None, rep_pic=story.rep_pic.url, extra_pics=extra_pics, writer_is_followed=None, ) story_dtos.append(story_dto) return story_dtos
view 에 many=Ture 없으니까 에러남. 다시 보자
class SamePlaceStorySelector: def __init__(self, user:User): self.user = user def list(self, story_id: int): story_place_subquery = Story.objects.filter(id=story_id).values('place') same_place_stories = Story.objects.filter(place=Subquery(story_place_subquery)).select_related('writer', 'place').prefetch_related('photos').exclude(id=story_id) story_dtos = [] for story in same_place_stories: extra_pics = [photo.image.url for photo in story.photos.all()[:3]] story_dto = SamePlaceStoryDto( id=story.id, title=story.title, place_name=story.place.place_name, preview=story.preview, writer=story.writer, writer_is_verified=story.writer.is_verified, nickname=story.writer.nickname, created=story.created, rep_pic=story.rep_pic.url, extra_pics=extra_pics, ) story_dtos.append(story_dto) return story_dtos
원래 Dto에서 None 쓰는건 있을수도 있고 없을수도 있는 필드라서 그런것.