카테고리 없음
[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 쓰는건 있을수도 있고 없을수도 있는 필드라서 그런것.