글 목록 API 새로 만들기
글 목록을 보여주는 API를 비롯해 글(article) CRUD와 좋아요, 북마크 하기를 위한 API를 만들었다.
이때 글 목록을 보여주는 API가 프론트의 여러 부분에서 호출받는다.
1. 전체 목록
2. 3일 이내 작성된 글들을 좋아요 갯수 순으로 내림차순 정렬해서 보여주는 기능
3. 북마크한 글 목록
4. 임의의 사용자가 작성한 글 모아보기
각 기능들은 글 목록을 보여준다는 점은 동일하고, 어떤 글들을 조회할 것인지만 다르다. 이에 따라 이 기능들을 같은 API에 연결하고, 해당 API에서 query string을 통해 쿼리셋을 filter 하는 방식으로 만들기로 하였다.
class ArticleView(generics.ListCreateAPIView):
"""ArticleView
get 요청시 querystring에 따라 원하는 조건에 맞는 게시글의 목록을 불러옵니다.
post 요청시 게시글을 작성하여 DB에 저장합니다.
Attributes:
permission_classes (list): 퍼미션의 리스트
paginations_class (Pagination): 페이지네이션
serializer_class (Serializer): 어떤 시리얼라이저를 이용하여 응답 데이터 형성할지 지정
queryset (QuerySet): 기본으로 get_queryset이 반환할 쿼리 셋(최신순 정렬된 전체게시글)
"""
permission_classes = [IsAuthenticatedOrReadOnlyExceptBookMark]
pagination_class = ArticlePagination
serializer_class = ArticleListSerializer
queryset = Article.objects.all().order_by("-created_at")
페이지네이션을 위해 generics.ListCreateAPIView를 사용한다. 이때 아무런 쿼리스트링이 지정되지 않았을 때 기본적으로 반환할 queryset을 전체 글의 최신순으로 지정해둔다.
def trending(self):
queryset = (
Article.objects.filter(created_at__gte=timezone.now() - timedelta(days=3))
.annotate(like_count=Count("likes"))
.order_by("-like_count", "-created_at")
)
return queryset
def bookmarked(self):
queryset = self.request.user.bookmarked_articles.all()
return queryset.order_by("-created_at")
def of_user(self):
user_id = int(self.request.GET.get("user_id", 0))
user = get_object_or_404(User, id=user_id)
return user.article_set.all().order_by("-created_at")
def get_queryset(self):
query_select = {
"trending": self.trending,
"bookmarked": self.bookmarked,
"user": self.of_user,
}
selection = self.request.GET.get("filter", None)
return query_select.get(selection, super().get_queryset)()
get_queryset 메소드를 오버라이딩한다.
filter 쿼리파라미터의 값을 기준으로 적절한 queryset반환 함수를 호출한다.