: 유저 (id), 제품 (id, 이미지, 이름, 서브카테고리, 가격), + 수량, 장바구니 id !
장바구니를 읽어오는 기능은 제품리스트를 불러오는 기능과 크게 다를 것이 없어서 쉽게 작성이 가능했다
차이점은 회원만 이용 가능하게 하기 위해서 @login_decorator
를 사용했다는 점이다
class CartListView(View):
@login_decorator
def get(self, request):
result = [{
"cart_id" : cart.id,
"user_id" : cart.user.id,
"product_id" : cart.product.id,
"product_name" : cart.product.name,
"product_price" : int(cart.product.price),
"product_image" : cart.product.images.first().url,
"sub_category_id" : cart.product.sub_category_id,
"quantity" : cart.quantity
} for cart in Cart.objects.filter(user = request.user)]
return JsonResponse({'results' : result}, status = 200)
장바구니 추가의 핵심기능은 이미 들어있는 상품을 다시 추가했을 때 해당 상품의 수량만 증가해야한다는 것이다
이를 해결하기 위해서 get_or_create()
를 사용했다
QuerySet API reference 에서 get_or_create()
검색해서 내용을 확인해보자
whatisthenext.tistory.com 좀 더 한글로 잘 풀어진 설명을 보고 싶으면 해당 글을 참고해보자
위의 내용대로 함수를 써서 추가기능을 구현하면 코드는 아래와 같다
@login_decorator
def post(self, request):
try:
data = json.loads(request.body)
product_id = data['product_id']
quantity = data['quantity']
cart, created = Cart.objects.get_or_create(
user_id = request.user.id,
product_id = product_id,
quantity = quantity
)
if not created:
cart.quantity += quantity
cart.save()
return JsonResponse({'message' : 'SUCCESS'}, status=201)
하지만 이렇게 장바구니 POST 기능을 만든다면 문제가 생긴다
같은 product_id
를 가지고 있더라도 quantity
를 다르게 입력하면 DB가 새로 생성된다는 점이다
여기서 사용 되는 것이 공식문서 내용의 defaults
다
원문과 번역본을 가져와서 보도록 하자
Any keyword arguments passed to get_or_create() — except an optional one called defaults — will be used in a get() call. If an object is found, get_or_create() returns a tuple of that object and False.
get_or_create()에 전달된 모든 키워드 인수(defaults라는 선택적 인수 제외)는 get() 호출에 사용됩니다. 객체가 발견되면 get_or_create()는 해당 객체의 튜플을 반환하고 False를 반환합니다.
간단하게 defaults
내에 포함된 인수는 get() 호출
에서 인식이 안되기에 현재 장바구니 api에서는 user_id
와 product_id
가 같다면 다른 DB는 생성이 안된다는 것이다
cart, created = Cart.objects.get_or_create(
user_id = request.user.id,
product_id = product_id,
defaults = {'quantity': quantity}
)
if not created:
cart.quantity += quantity
cart.save()
위와 같이 코드 수정 후 POST를 실행해보면 원하던대로 기능이 실행되는 것을 볼 수 있다
PUT
DB에서 필요한 업데이트 내용이 하나더라도 항상 모든 필드를 새로운 값으로 업데이트한다
PATCH
DB에서 필요한 업데이트 내용이 일부면 해당 필드값만 가져와서 해당 부분만 업데이트한다
장바구니에서 수정할 값은 quantity
하나 뿐이라서 PATCH 를 사용했다
@login_decorator
def patch(self, request, cart_id):
try:
data = json.loads(request.body)
user = request.user
cart = Cart.objects.get(id = cart_id, user= user)
cart = Cart.objects.get(user_id = user.id)
cart.quantity = data['quantity']
cart.save()
return JsonResponse({'message' : 'SUCCESS'}, status=201)
장바구니에 들어있는 상품을 삭제할 때는 cart_id
에 해당하는 DB를 지우면 된다
@login_decorator
def delete(self, request, cart_id):
user = request.user
cart = Cart.objects.get(id = cart_id, user = user)
cart.delete()
return JsonResponse({'message' : 'SUCCESS'}, status = 204)
모든 코드에 [API] 제품리스트
때와 동일하게 try
/ except
를 사용해서 필터링 하는 곳은 'DOES NOT EXISTS' / 키 에러가 나는 곳은 'KEY_ERROR' 을 넣어주자
장바구니도 끝 !!