TIL-041 | 꾸며줘 홈즈 project(4)_메뉴 뷰, 상품리스트 구현하기

Lee, Chankyu·2021년 11월 21일
0
post-thumbnail
post-custom-banner

📝 메인페이지 - MenuList API 구현

✅ 코드 작성에 앞서, 집 꾸미기 사이트 메인페이지 Category는 Category 안에 Subcategory가 있고, 또 그 Subcategory안에 다음 Subcategory가 있는 형태였기에 프론트엔드 담당자와의 소통이 중요하다고 판단하였다. 프론트에서 원하는 데이터 형식을 문의하였고, 지속적인 논의를 진행하였다.

✔ 작성한 code

class MenuListView(View):
    def get(self, request):
        menus = Menu.objects.prefetch_related('category_set', 'category_set__subcategory_set')

        menu_data = [{
            'menu_id'   : menu.id,
            'menu_name' : menu.name,
            'image_url' : menu.image_url,
            'categories'  : [{
                'id'   : category.id,
                'name' : category.name,
                'subcategories'   : [{
                    'id'   : subcategory.id,
                    'name' : subcategory.name,
                } for subcategory in category.subcategory_set.all()],
            } for category in menu.category_set.all()],
        } for menu in menus]

        return JsonResponse({'menus':menu_data}, status = 200)
  • 메인페이지의 Menu, Category, Subcategory의 구현을 위해 MenuListView 클래스를 생성하였다.

  • 데이터 형식은 프론트엔드 담당자와 논의 하여 결정하였고, 원하는 Json 형식의 데이터를 보내고자 위와 같은 코드를 작성하였다.

  • 사실 위와 같은 데이터 형식은 DB에 요청하는 Query의 횟수가 매우 높을 수 밖에 없었다. 따라서 prefetch_releated를 사용한 ORM 최적화를 통해 좀 더 효율적인 데이터 호출을 구현하였다.

메뉴 리스트 구현 스크린 샷


📝 상품페이지 - 상품전체 List API 구현

✅ 전체 상품리스트 데이터를 호출하여 프론트엔드 담당자와 논의하여 설정한 한 페이지당 상품 갯수를 설정하는 것과 호출한 데이터를 낮은가격순, 높은가격순, 별점순으로 Filtering 하는 것이 주요 구현 사항이었다.

✔ 작성한 code

class ProductGroupsView(View):
    def get(self, request):
        sub_category_id = request.GET.get("SubCategoryId")
        ordering        = request.GET.get("ordering")
        OFFSET          = int(request.GET.get("offset", 0))
        LIMIT           = int(request.GET.get("limit", 16))

        product_groups = ProductGroup.objects.filter(sub_category_id = sub_category_id).annotate(
            best_ranking      = Avg('review__star_rate'),
            review_count      = Count('review'),
            review_star_point = Avg('review__star_rate'),
            discounted_price  = F('displayed_price') - F('displayed_price') * (F('discount_rate')/100),
            latest_update     = F('created_at')
        ).order_by(ordering)[OFFSET:OFFSET+LIMIT]
        
        results = [
            {
            'id'               : product_group.id,
            'company'          : product_group.company,
            'product_name'     : product_group.name,
            'price'            : float(product_group.displayed_price),
            'image_url'        : product_group.productimage_set.all()[0].image_url,
            'discount_rate'    : float(product_group.discount_rate),
            'discounted_price' : float(round(product_group.discounted_price,0)),
            'star_point'       : float(product_group.review_star_point),
            'review'           : product_group.review_count
            }for product_group in product_groups]

        return JsonResponse({'product_groups':results}, status = 200)
  • SubCategory 별로 호출하는 데이터의 종류가 달라지기 때문에 SubCategoryID를 첫 번째 query parameter로 설정하였고, filtering(ordering)의 기준을 두 번째 query parameter로 설정하였다.

  • 프론트엔드 담당자와 논의하여 한 페이지당 상품 갯수를 16개로 설정하였기에 LIMIT의 default 값을 16으로 설정하였다.

  • 호출된 데이터들의 filtering을 구현하고자 annotate를 통해 가상필드를 생성하여 원하는 데이터를 얻고, order_by()로 정렬하였다. order_by()의 기준은 두 번째 query parameter(ordering)로 설정하였다.

전체 상품 리스트 구현 스크린 샷

profile
Backend Developer - "Growth itself contains the germ of happiness"
post-custom-banner

0개의 댓글