✅ 코드 작성에 앞서, 집 꾸미기 사이트 메인페이지 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 최적화를 통해 좀 더 효율적인 데이터 호출을 구현하였다.
✔ 메뉴 리스트 구현 스크린 샷
✅ 전체 상품리스트 데이터를 호출하여 프론트엔드 담당자와 논의하여 설정한 한 페이지당 상품 갯수를 설정하는 것과 호출한 데이터를 낮은가격순, 높은가격순, 별점순으로 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)로 설정하였다.
✔ 전체 상품 리스트 구현 스크린 샷