Project : WASH Korea [API]제품리스트 (1)
위코드 1차 프로젝트
[API] 제품리스트
멘토님의 팁 !
어떻게 시작해야할지 감이 안잡힌다면
- 모든 상품 정보를 GET 해오는 코드 작성
- 필터링 으로 원하는 부분만 GET 해오는 코드 작성
- 쿼리파라미터로 필터링 처리
+
Q객체 사용법
순으로 작성해보면 쉬울 것이라고 하셨다
멘토님의 팁 !
어떻게 시작해야할지 감이 안잡힌다면
- 모든 상품 정보를 GET 해오는 코드 작성
- 필터링 으로 원하는 부분만 GET 해오는 코드 작성
- 쿼리파라미터로 필터링 처리
+
Q객체 사용법
순으로 작성해보면 쉬울 것이라고 하셨다
필요한 정보
: 제품 이미지, 태그, 이름, 서브이름, 가격 + 제품 id !
1. 전체 상품 정보를 GET
class ProductListView(View):
def get(self, request):
results = [{
"id" : product.id,
"name" : product.name,
"sub_name" : product.sub_name,
"price" : int(product.price),
"tags" : [tag.name for tag in product.tags.all()],
"product_image" : product.images.first().url
} for product in Product.objects.all()]
return JsonResponse({'results' : results}, status = 200)
tags
와 image
는 둘 다 one to many 관계지만 현재 페이지에서 tags
는 모든 내용이 필요한 반면, image
는 메인 이미지 한 장만 있으면 되기에 서로 다른 방법을 사용했다
또한 여기서 product.images.first().url
역참조 관계인 Product
에서 ProductImage
를 정참조처럼 불러올 수 있는 이유는 related name 을 사용했기 때문이다
# products/models.py
class ProductImage(models.Model):
url = models.CharField(max_length=2000)
product = models.ForeignKey('Product', on_delete=models.CASCADE, related_name='images')
class Meta:
db_table = 'product_images'
처음에는 for문을 사용해서 작성했지만 리스트 컴프리헨션을 사용하니 훨씬 깔끔해진 코드를 볼 수 있다
2. 필터링 사용
class ProductListView(View):
def get(self, request):
results = [{
"id" : product.id,
"name" : product.name,
"sub_name" : product.sub_name,
"price" : int(product.price),
"tags" : [tag.name for tag in product.tags.all()],
"product_image" : product.images.first().url
} for product in Product.objects.filter(sub_category_id = 1)]
return JsonResponse({'results' : results}, status = 200)
.filter
메소드를 사용해서 서브카테고리 1번에 해당하는 제품만 불러올 수 있게 변경해 주었다
쿼리파라미터 / 패스파라미터
쿼리파라미터를 이용하기 전에 어떤 개념인지 먼저 알아보자
1. 쿼리파라미터
주로 데이터를 특정 조건으로 검색하거나 정렬하고자 할 때 활용되는 방식
Query Parameter으로 전송된 API에 대응하기 위해서 URL 패턴 정의를 따로 해주어야 하는 부분은 없다
대신 View 함수
에서 해당 Parameter에 접근하기 위해서는 HTTP Method에 따라 request.GET
또는 request.POST
로 QueryDict 객체를 호출해야 한다
QueryDict 객체는 Dictionary의 subclass로 key와 value형식으로 이루어져 있기 때문에, 전달되는 변수를 키값으로 조회해서 데이터를 처리하면 된다
2. 패스파라미터
커머스 사이트의 제품 상세 페이지에 대한 정보를 요청할 때 자주 사용
장고에서 Path Variable로 리소스에 대한 정보를 받아서 처리하기 위해서는 <>기호
를 통해서 urlpattern을 정의해야 한다
3. 쿼리파라미터로 필터링
class ProductListView(View):
def get(self, request):
category = request.GET['category']
sub_category = request.GET.get('sub_category')
if category:
Products = Product.objects.filter(sub_category_id__category_id = category)
if sub_category:
Products = Product.objects.filter(sub_category_id = sub_category)
results = [{
"id" : product.id,
"name" : product.name,
"sub_name" : product.sub_name,
"price" : int(product.price),
"tags" : [tag.name for tag in product.tags.all()],
"product_image" : product.images.first().url
} for product in Products]
return JsonResponse({'results' : results}, status = 200)
카테고리와 서브카테고리로 각각 필터링을 주었다
여기서 category = request.GET['category']
, sub_category = request.GET.get('sub_category')
두 가지 방법은 무엇이 다른 것일까 ?
답은 get() 메서드
의 사용법에서 찾을 수 있다
get() 메서드
는 키값이 딕셔너리 안에 있으면 밸류값을 리턴해주고 키값이 존재하지 않으면 디폴트값 None
을 리턴한다 ( 물론 디폴트 값을 직접 정해줄 수 도 있다 )
따라서 현재 코드에선 category
가 없으면 에러가 발생하고 sub_category
는 없어도 된다 ( category
전체 제품 리스트 호출 )
러쉬코리아 홈페이지에서 확인을 해보면 카테고리별 전체 제품 보기는 있어도 러쉬의 모든 제품을 모든 페이지는 없기에 카테고리 코드는 category = request.GET['category']
처럼 작성해서 항상 쿼리파라미터가 있도록 작성했다
4. 가격 순 정렬
제품리스트 페이지에는 다양한 정렬 기능이 존재한다
가격 높은 순, 낮은 순으로만 먼저 정렬 기능을 만들어 보자
쿼리파라미터에 price
만 추가하면 된다
class ProductListView(View):
def get(self, request):
category = request.GET['category']
sub_category = request.GET.get('sub_category')
price = request.GET.get('price')
if category:
Products = Product.objects.filter(sub_category_id__category_id = category)
if sub_category:
Products = Product.objects.filter(sub_category_id = sub_category)
if price:
Products = Products.order_by(price)
results = [{
"id" : product.id,
"name" : product.name,
"sub_name" : product.sub_name,
"price" : int(product.price),
"tags" : [tag.name for tag in product.t정ags.all()],
"product_image" : product.images.first().url
} for product in Products]
return JsonResponse({'results' : results}, status = 200)
👏 멘토님 리뷰 👏
현재 방식으로 작성할 경우 정렬기능이 추가될 때 마다 계속 쿼리파라미터와
if문
을 추가로 만들어줘야 한다정렬될 내용을 묶음으로 만드는 것이 훨씬 깔끔하게 보이고 스스로가 편하다
ex.
class ProductListView(View): def get(self, request): sorting = request.GET.get('sort', 'id') ... sort = { "id" : "id" "price" : "price", "-price" : "-price", }
너무나 당연한 말이다 러쉬홈페이지만 봐도 추천을 기본 순으로 본다면 4개의 정렬이 만들어져야 한다
바로 반영해서 코드를 수정해 주었다
class ProductListView(View): def get(self, request): category = request.GET['category'] sub_category = request.GET.get('sub_category') sorting = request.GET.get('sort', 'id') if category: Products = Product.objects.filter(sub_category_id__category_id = category) if sub_category: Products = Product.objects.filter(sub_category_id = sub_category) sort = { "id" : "id", "price" : "price", "-price" : "-price", } results = [{ "id" : product.id, "name" : product.name, "sub_name" : product.sub_name, "price" : int(product.price), "tags" : [tag.name for tag in product.t정ags.all()], "product_image" : product.images.first().url } for product in Products] return JsonResponse({'results' : results}, status = 200)
그러면 Q객체
는 언제 쓰는 걸까 ???
다음 글에서 만나봅시다 !!!
Author And Source
이 문제에 관하여(Project : WASH Korea [API]제품리스트 (1)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gyuls/Project-WASH-Korea-API제품리스트-1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)