피드 모델을 작성 시간(최신순)으로 정렬하는 방법은 created_at 필드를 이용하거나 id 필드를 이용하는 방법이 있다.
(id는 점점 커지는 특성이 있다.)
from feed.models import Feed
Feed.objects.order_by("-created_at")
Feed.objects.order_by("-id")
기본적인 정렬은 이렇게 쉽게 구현할 수 있지만 기능을 점점 확장시키다 보면 좀 더 다양한 방법으로 정렬을 할 필요성이 생긴다.
이번 green_door프로젝트를 진행하면서 내가 생각한 문제와 그 해결법을 정리해보겠다.
내가 북마크한 피드를 마이페이지에서 보여줘야 하는데 어떤 기준으로 정렬시켜서 보여줘야 할까?
가장 간단한건 일반 피드와 마찬가지로 최신순으로 정렬하는 거지만 내가 옛날 게시물을 북마크 했는데 그게 맨 뒤에 있다면 불편함을 느낄 거 같았다. 그래서 북마크 한 순서대로 정렬을 해보기로 하고 기능을 구현해봤다.
greendoor.models.py
from django.db import models
# Create your models here.
class BaseModel(models.Model):
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
feed.models.py
from typing import Any, List
from django.db import models
from greendoor.models import BaseModel
from user.models import Users
class Feed(BaseModel):
user_id = models.ForeignKey(Users, on_delete=models.CASCADE, related_name="feed", db_column="user_id")
title = models.CharField(max_length=100)
image = models.CharField(max_length=256)
content = models.CharField(max_length=500, blank=True, null=True)
like_count = models.IntegerField(default=0)
my_likes: List[Any] # Prefetch 에서 사용용
my_bookmark: List[Any] # Prefetch 에서 사용용
class FeedBookmark(BaseModel):
user_id = models.ForeignKey(Users, on_delete=models.CASCADE, related_name="feed_bookmark", db_column="user_id")
feed_id = models.ForeignKey(Feed, on_delete=models.CASCADE, related_name="feed_bookmark", db_column="feed_id")
class Meta:
constraints = [
models.UniqueConstraint(fields=["user_id", "feed_id"], name="unique_user_feedbookmark"),
]
feed.services.feed_service.py
# 내 피드 조회 함수
def get_my_feed_list(user_id: int) -> QuerySet[Feed]:
return (
Feed.objects.order_by("-created_at")
.prefetch_related(
Prefetch(
"feed_like",
queryset=FeedLike.objects.filter(user_id=user_id),
to_attr="my_likes",
),
Prefetch(
"feed_bookmark",
queryset=FeedBookmark.objects.filter(user_id=user_id),
to_attr="my_bookmark",
),
)
.filter(user_id=user_id)
)
# 내가 북마크한 피드 조회 함수
def get_my_bookmark_feed_list(user_id: int) -> QuerySet[Feed]:
return (
Feed.objects
.prefetch_related(
Prefetch(
"feed_like",
queryset=FeedLike.objects.filter(user_id=user_id),
to_attr="my_likes",
),
Prefetch(
"feed_bookmark",
queryset=FeedBookmark.objects.filter(user_id=user_id),
to_attr="my_bookmark",
),
)
.filter(feed_bookmark__user_id=user_id) # 역참조 관계에 있는 필드를 가져오려면 언더바 2개 사용
.order_by("-feed_bookmark__created_at") # 역참조 관계에 있는 북마크 테이블의 최근 생성 순으로 정렬
)
처음엔 많이 해멨는데 related_name을 쓰고 __(언더바 2개)를 사용하면 역참조 된 모델의 필드도 사용할 수 있다는 걸 알고 나선 쉽게 구현이 되었다. annotate를 사용해서 현재 모델의 필드로 재정의(?)를 해도 되지만 북마크 모델의 created_at 필드는 조회 말고는 따로 사용할 필요가 없어서 바로 참조를 했다.
'코딩 > Django' 카테고리의 다른 글
[Django] F( )표현식 (0) | 2022.04.26 |
---|---|
Django channels 실시간 채팅 기능 (websocket) (3) | 2022.03.06 |