코딩 개발일지

카테고리 필드 없이 나누기 (좋아요많은 순 / 국가별) 본문

AI 본 교육/AI 14주차

카테고리 필드 없이 나누기 (좋아요많은 순 / 국가별)

호기호 2023. 11. 21. 10:01

1. 목적 및 개요

메인페이지에서 보여주는 게시글 리스트들을 카테고리별로 보여주기위해 작성한 메서드입니다.

[ 최신순 / 인기글TOP8 / 국가선택 후 인기글TOP8 ] 세 가지 카테고리를 나누어 GET요청을 받습니다.

2. 요구 사항

  • [ 최신순 ] 리스트는 카테고리를 선택하지 않았을 때의 기본값이다.
  • [ 최신순 ] 리스트(기본값)는 한 페이지당 8개의 pagination을 적용시킨다.
  • [ 인기글TOP8 / 국가선택 후 인기글TOP8 ] 의 카테고리는 pagination을 적용시키지 않는다.
  • 싫어요 개수가 5개이상인 게시글은 데이터를 보내주지 않는다.

3. 설계

  • 최신순
    settings.py에 REST_FRAMEWORK 기능인 pagination 설정을 한다. 프론트엔드에서 page_info가 필요하므로 Response에 추가한다.
    Story에 있는 게시글 중 싫어요 4개 초과는 제외하고, 최신 생성 순으로 가져온다.
  • 인기글 TOP8
    Story에 있는 게시글 중 싫어요 4개 초과는 제외하고, 최신 생성 순으로 가져온다.
  • 국가선택 후 인기글 TOP8
    urls.py에 str:author_country를 포함시켜 프론트엔드에서의 국가선택 value값과 일치할 때, GET요청을 받는다.
    Story에 있는 게시글 중 싫어요 4개 이하이고, 작성자의 국가가 author_country와 일치하는 조건을 만족하는 게시글을 최신 생성 순으로 가져온다.

4. 코드

<views.py>

class StorySortedByLikeView(APIView):
    def get(self, request):
        """
        모든 게시물을 좋아요 순으로 8개만 Response 합니다.
        """        
        stories = Story.objects.exclude(hate_count__gt=4).order_by('-like_count', '-created_at')[:8] # 좋아요 많은순 / 최신순
        serializer = StoryListSerializer(stories, many=True)
        return Response({'status': '200', 'story_list': serializer.data}, status=status.HTTP_200_OK)
        
        
class StorySortedByCountryView(APIView):
    def get(self, request, author_country):
        """
        국가별 게시물을 좋아요 순으로 8개만 Response 합니다.
        """
        stories = Story.objects.filter(hate_count__lte=4, author__country=author_country).order_by('-like_count', '-created_at')[:8] # 국가별 / 좋아요 많은순 / 최신순
        serializer = StoryListSerializer(stories, many=True)
        return Response({'status': '200', 'story_list': serializer.data}, status=status.HTTP_200_OK)


class StoryView(APIView):
    def get(self, request, story_id = None):
        """
        story_id가 없을 경우 모든 계시물을 Response 합니다.
        story_id가 있을 경우 특정 게시물을 Response 합니다.
        """
        page = request.GET.get('page', 1)
        per_page = settings.REST_FRAMEWORK['PAGE_SIZE']
        
        if story_id is None:
            stories = Story.objects.exclude(hate_count__gt=4).order_by('-created_at') # 최신순
            paginator = Paginator(stories, per_page)
            try:
                stories_page = paginator.page(page)
            except PageNotAnInteger:
                stories_page = paginator.page(1)
            except EmptyPage:
                stories_page = paginator.page(paginator.num_pages)
            serializer = StoryListSerializer(stories_page, many=True)
            page_info = {
                'current_page': stories_page.number,
                'total_pages': paginator.num_pages,
                'total_items': paginator.count,
            }
            return Response({'status': '200', 'story_list': serializer.data, 'page_info': page_info}, status=status.HTTP_200_OK)
        else:
            """상세 페이지"""

						(생략)

<settings.py>

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 8,

		(생략)

    )
}

<urls.py>

urlpatterns = [
    path('',views.StoryView.as_view(), name='story_view'),
    path('like_sorted/',views.StorySortedByLikeView.as_view(), name='story_sorted_like_view'),
    path('country_sorted/<str:author_country>/',views.StorySortedByCountryView.as_view(), name='story_sorted_country_view'),
    
		(생략)

]

이렇게 작성한 후, 프론트엔드에서 fetch요청을 할 때, 필요한 url주소를 fetch해주면, 원하는 데이터를 프론트엔드에서 띄울 수 있다.