ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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 쓰는건 있을수도 있고 없을수도 있는 필드라서 그런것.

Designed by Tistory.