팀, 포지션 간 의사소통 중요. 2차 프로젝트에서도 마찬가지로 발표가 중요. 발표까지가 프로젝트.
results = json.loads(request.body)['results']
user_id = request.user.id
for result in results:
product_id = result['product_id']
quantity = result['quantity']
product_option_id = result['product_option_id']
product_option_quantity = result['product_option_quantity']
어제 하던 것에 수정하기
class CouponRegistryView(View):
@transaction.atomic
# 연속적인 작업이므로 트렌젝션 아토믹
@auth_check
# 모든 작업에는 유저의 토큰이 가야한다.
def post(self, request):
try:
data = json.loads(request.body)
name = data['name']
discount_price = data['discount_price']
issue_date = data['issue_date']
expire_date = data['expire_date']
# 쿠폰을 만들기 위해 받는 자료
sub_category = SubCategory.objects.get(name=data['sub_category_name'])
coupon = Coupon.objects.create(
name = name,
discount_price = discount_price,
issue_date = issue_date,
expire_date = expire_date
)
# 쿠폰 만들기
coupon_sub_category = CouponSubCategory.objects.create(coupon=coupon, sub_category=sub_category)
# 쿠폰의 서브카테고리도 따로 뷰 만들지 않고 만들 수 있다.
return JsonResponse({'message' : 'SUCCESS'}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status=400)
except JSONDecodeError:
return JsonResponse({'message' : 'JSON_DECODE_ERROR'}, status=400)
class UserCouponView(View):
@transaction.atomic
@auth_check
# 마찬가지로 트랜잭션, 데코레이터 토큰 처리
def post(self, request):
try:
data = json.loads(request.body)
coupon = Coupon.objects.get(id=data['coupon_id']).id
user = request.user.id
# 데코레이터 처리로 인한 변경
quantity = data['quantity']
user_coupon, is_created = UserCoupon.objects.get_or_create(
coupon_id = coupon,
user_id = user,
defaults = {'quantity' : quantity}
)
if not is_created:
user_coupon.quantity += data['quantity']
user_coupon.save()
# 쿠폰도 unique_toghether 되어 있는 상황
# 데이터에 직접 수량이 변하는 것을 입력해야 하므로 get_or_create 및 if문 처리 ; 저번 블로그 설명 참고
return JsonResponse({'message' : 'SUCCESS'}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status=400)
except JSONDecodeError:
return JsonResponse({'message' : 'JSON_DECODE_ERROR'}, status=400)
여기까지 쿠폰을 등록하고 유저와 관계를 맺고나면 다음과 같은 상황이 주어진다.
import json
from django.db import transaction
from django.db.utils import DataError
from django.views import View
from django.http import JsonResponse
from product.models import (
Category, SubCategory, Product,
ProductImage, Option, ProductOption
)
from user.models import User, Coupon, UserCoupon
from order.models import Order
from utils.decorators import auth_check
class ApplyCouponView(View):
@auth_check
@transaction.atomic()
# 마찬가지로 트랜젝션 및 토큰
def post(self, request):
try:
data = json.loads(request.body)
user_id = request.user.id
product_id = data['product_id']
# 먼저 유저 정보를 토큰으로 가져오고 프론트엔드가 유일하게 주는 product_id 하나를 구한다. 예시로 15번을 사용했다.
user_coupons = UserCoupon.objects.filter(user_id = user_id)
user_coupon_list = [user_coupon.coupon_id for user_coupon in user_coupons]
# 쉘을 찍어서 확인해본 결과 유저 아이디를 먼저 필터링한 후(3으로 했다.) -> 오브젝트로 나온 값에 대해서 coupon_id값만 리스트 컴프리핸션으로 리스트로 만든다.
sub_category = Product.objects.get(id=product_id).sub_category
# 내가 아는 정보는 product_id 하나뿐이다. 따라서 이를 최대한 이용해서 서브 카테고리까지 뽑아낸다.
sub_category_coupons = sub_category.couponsubcategory_set.all()
# 쿠폰으로 가려면 역참조를 해야한다. 역참조 공식에 따라 서브카테고리로 모든 쿠폰 서브카테고리의 내용을 가져온다.
sub_category_coupon_list = [sub_category_coupon.coupon_id for sub_category_coupon in sub_category_coupons]
# 이를 coupon_id값만 리스트 컴프리헨션으로 리스트를 만든다.
result = []
for i in user_coupon_list:
if i in sub_category_coupon_list:
result.append(i)
# 이후 두 값을 비교하는데 for 문을 통해 있는지 없는지 확인 후 append 해준다.
coupon_name = []
for j in result:
coupon = Coupon.objects.get(id=j)
coupon_name.append(coupon.name)
# 그렇게 나온 공통적인 coupon_id를 구했다면 반대로 그 name을 구해준다.
# 여기서 주의할 점 : return을 여기서하면 has_heager에러가 난다. 즉 json을 리턴할 수 없기 때문.
return JsonResponse({'message' : 'SUCCESS', 'coupon_name' : coupon_name}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status=400)
except JSONDecodeError:
return JsonResponse({'message' : 'JSON_DECODE_ERROR'}, status=400)
for문이 너무 많다. 효율적인 코드라고는 할 수 없어 멘토님과 상의 결과 나중에 더 고민해길 바라는 코드였다. 오늘 반나절 정도 고민한 코드고 많이 물어보며 한 만큼 값진 결과물이었다. 이제 프론트랑 맞춰보면 되겠다.
무슨소리인가 하면 쿠폰이 생성될 때 한 제품군에만 되는게 아니라 여러 제품군에 내가 원하는거에 매핑시키는 것.
예를 들어 '할인쿠폰1, 2, 3 등 여러 개가' 이 생겼는데 양말 말고도 덧신, 신발에도 적어 넣기만 하면 주르륵 생기는 것.
해당 부분 코드(user/views.py)
coupons = Coupon.objects.all()
for coupon in coupons:
coupon_sub_category = CouponSubCategory.objects.create(
coupon=coupon,
sub_category=sub_category
)
고민한 것 : 분명 for loop을 해줘야 하는데 어떤 것을 기준으로 for loop을 해줘야할지 몰라 초반에는 get_or_create, 그냥 for loop 을 돌렸는데 우연히 장고 쉘에서 coupon을 중심으로 돌렸더니 데이터가 생기는 것을 목격.
하지만 coupon이 iterable하지 않기 때문에 다른 방법이 필요.
해결 : 결론은 쿠폰을 제대로 정의해주지 않았기 때문. 그냥 오브젝트일 뿐인 것을 정의해줄 "coupons = Coupon.objects.all()"를 붙인 뒤 해줬더니 완벽하게 적용되었다.(쿼리셋을 루프해주는 방법을 찾아봄)
쿼리셋을 loop 하는 완벽한 방법
참고 사이트