Django를 활용해 장바구니에 물품담는 POST API를 구현하면서 get_or_create
라는 method와 키워드 인수인 defaults를 사용하게 되었다.
이 과정에서 defaults가 정확히 어떻게 활용되는건지 설명해준 자료를 쉽게 찾지 못해 애를 먹었다. 어렵게 알아낸만큼 기록을 하여, 필자도 기록하고 블로그를 방문해준 개발자분들께 도움을 드리고자 한다.
get_or_create
가 어떤 메소드인지 알아보자.
object, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday': date(1940, 10, 9)},
)
get_or_create(**kwargs)
는 주어진 객체 kwargs(모델의 모든 필드에 기본값이 있는 경우 비어 있을 수 있음)를 사용하여 객체를 검색하고 필요한 경우 생성하는 편리한 방법이다.
get_or_create
메서드는 (object, created) 라는 튜플 형식으로 반환을 한다. 첫번째 인자(object)는 우리가 꺼내려고 하는 모델의 인스턴스(객체)이고, 두번째 인자(created)는 boolean flag이다.
flag란, TRUE 또는 FALSE를 갖는 온오프 스위치라고 생각하면 된다. 딸깍하고 스위치를 키면 TRUE, 스위치를 끄면 FALSE이다.
get_or_create
메서드를 간단히 정리하면 아래의 두 가지 경우로 설명이 가능하다.
**kwargs
에 들어간 조건에 해당하는 인스턴스가 존재한다면 데이터 베이스에서 해당 인스턴스를 꺼내와 object에 대입하고, flag는 False가 된다. 즉, created(boolean flag)는 get_or_create
메서드에 의해 생성이 되면 True, 생성되지 않고 데이터베이스에서 꺼내오면 False가 된다.
아래는 필자가 개발하던 API에서 Cart의 model 부분과 get_or_create
를 사용한 부분이다.
# Cart models.py
class Cart(TimeStampModel):
quantity = models.IntegerField()
product = models.ForeignKey(Product, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
db_table = 'carts'
# get_or_create 사용한 views.py
product = Product.objects.get(id=data['product_id'])
cart, created = Cart.objects.get_or_create(
defaults = {'quantity' : quantity},
product = product,
user = request.user
)
if not created:
cart.quantity += quantity
cart.save()
return JsonResponse({"message" : "CART_QUANTITY_CHANGED"}, status=200)
return JsonResponse({"message" : "PUT_IN_CART_SUCCESS"}, status=201)
장바구니(Cart)에 물품(product)을 담을 때, 해당 사용자(request.user)가 이미 동일한 물품을 장바구니에 가지고 있다면 장바구니의 물품 수량(quantity)을 update 해주고, 만약 장바구니에 해당 물품을 가지고 있지 않다면 장바구니 data를 생성해주는 코드이다.
장바구니에 물품이 추가되는지, 아니면 수량이 업데이트되는지의 기준은 '해당유저'의 장바구니에 '해당물품'이 존재하는가 이다. 다르게 말하면, 장바구니에 해당물품이 몇 개(quantity)가 있는지는 get_or_create
의 기준이 아니다.
하지만, 해당 물품이 장바구니에 존재하지 않아 create 해야한다면 quantity에 값을 넣어줘야 한다. 이런 경우에 defaults
가 사용된다.
즉, get_or_create
메서드가 get을 할 것인지, create을 할 것인지를 판단할 때는 필요하지 않지만, create을 할 때 필요한 키를 정의하기 위해서 키워드 인수로 사용하는 것이다.