본문 바로가기

카테고리 없음

DRF + ML 2일차

글 목록 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반환 함수를 호출한다.