jiiheee's 개발 일지

[Django] 장바구니 API 구현하기 본문

📚 Study/Django

[Django] 장바구니 API 구현하기

◼️ 2023. 12. 15. 15:04

목표

  • 물품과 개수를 받아서 DB에 저장

초반 디자인 고민

초반에 어떻게 구현해야 할지 고민을 꽤 오래 했다. 어떤 앱에 속해있는 게 이질감이 들고 새로 앱을 만들기에는 DB에 어떻게 저장해야 할지 고민이 됐다. 장바구니라는 것이 물건을 고르면 리스트처럼 쌓여야 하는데 그 부분을 어떻게 표현해야 할지 감이 오지 않았다. 

 

그러다 문득 기존에 사용중인걸 생각해 보라는 친오빠의 말에 쿠팡 장바구니를 들어가 url을 확인했다. 

'https://cart.coupang.com/cartView.pang'으로 돼있는 것을 확인 후 앱을 새로 만들어야겠다고 생각했다. (역시 경력자의 조언은 옳다..)

 


cart app 생성 및 기본 설정

app 생성 코드 명령어를 통해 cart 앱을 생성시킨다.

python manage.py startapp cart

 

shop_api / settings.py 'cart' 추가

INSTALLED_APPS = [

    # ... 중간 코드 생략

    'cart.apps.CartConfig'
]

 

shop_api / urls.py 'cart' 추가

urlpatterns = [

   # ... 중간 코드 생략
 
    path('cart/', include("cart.urls"))
]

cart / models.py 'Cart' model 추가

from django.db import models

class Cart(models.Model):
    user = models.ForeignKey("user.User", on_delete=models.CASCADE, db_column="user_id")
    product = models.ForeignKey("product.Product", on_delete=models.CASCADE, db_column="product_id")
    product_quantity = models.IntegerField()

DB에 저장할 때는 user_id, product_id로 저장되지만 실질적으로는 User의 user_id와 일치시킬 것이고 Product의 product_id와 일치시켜서 볼 것이기 때문에 user와 product를 ForeignKey로 작성한다.


cart / urls.py 'add/' 추가

from django.urls import path
from . import views
from .views import CartaddView

urlpatterns = [
    path("add/", CartaddView.as_view())
]

추후에 장바구니에서 삭제하는 코드도 필요할테니 'add/'로 작성하였다.


cart / views.py 'CartAddView' 추가

이 과정에서 요청자로부터 데이터를 받는데까지는 잘 넘어오는데 DB에 저장하는 과정에서  'Field 'id' expected a number but got ('1',).' 이런 에러가 났다. 에러 내용을 직역하면 필드 "'id'에 숫자를 기대했지만, ('1')이 들어왔다"이다.

 

또 이 문제를 이해하기까지 많은 고민을 했다. 숫자를 기대했는데 ('1')이 들어왔다는 얘기가 도대체 무슨 얘기일까...

 

문제가 생겼을 때 해결하기 위해서는 다양한 방법들이 있다. 나는 아래 세 가지 방법을 통해서 문제를 해결했다.

 

  1. Debugging 돌리기: 각 스탭을 돌려보며 어디가 문제인지 문제 구간을 찾을 수 있다.
  2. Try, exception 활용하기: 문제 구간을 찾았다면 try로 묶고 exception으로 에러 부분을 빼서 확인할 수 있다. (코드는 아래 참고)
  3. 로그 찍기: 에러 부분을 로그로 찍어서 더 명확하게 확인할 수 있다.
class CartaddView(APIView):

	# ... (중간 코드 생략)
    
        try:
            Cart.objects.create(
                user_id=user_id,
                product_id=product_id,
                product_quantity=product_quantity
            )
        except Exception as e:
        	print(e)
            
        return HttpResponse('장바구니에 담겼습니다.')

 

debugging을 해보니 요청자로부터 data를 받는 과정에서 (('1'),  ,) 이렇게 받아진 것을 확인했다.

정상적으로 받아졌다면 (1, , ) 이렇게 들어왔어야 한다. 이래서 숫자를 기대했지만 ('1')이 들어왔다고 했구나 싶었다.

 

코드를 자세히 보니 user_id를 받는 과정에서 객체로 받는 것이 문제였다.

 

이를 구별하기 위해서 '_id'를 추가하였다. 이 과정을 통해서 객체에 대한 공부가 부족함을 깨달았다. FastAPI로 첫 번째 프로젝트 했을 때 class를 거의 활용하지 않았던 부분이 여기서 드러났다. 이번 기회를 통해서 부족한 부분을 알 수 있었고 채울 수 있어서 다행이라고 생각했다.

from django.shortcuts import render
from django.http import HttpResponse
from rest_framework.views import APIView
from cart.models import Cart

class CartaddView(APIView):
    def post(self, request):
        user_id = request.data.get("user_id")
        product_id = request.data.get("product_id")
        product_quantity = request.data.get("product_quantity")
        
        Cart.objects.create(
            user_id=user_id,
            product_id=product_id,
            product_quantity=product_quantity
        )
        return HttpResponse('장바구니에 담겼습니다.')
        
 ###수정 전 코드####
#class CartaddView(APIView):
#    def post(self, request):
#        user = request.data.get("user_id"),
#        product = request.data.get("product_id"),
#        product_quantity = request.data.get("product_quantity")
        
#        Cart.objects.create(
#            user_id = user,
#            product_id = product,
#            product_quantity = product_quantity
#        )
#        return HttpResponse('장바구니에 담겼습니다.')

결과