1차 프로젝트 기능구현(feat . Brokurly)

성종호·2021년 12월 12일
0
post-custom-banner

기능구현

내가 구현한 기능

  • 커머스 상세페이지
  • 커머스 주문페이지

상세페이지 전체 코드

class ProductDetailView(View):
    def get(self, request, product_id):
        try:
            product = Product.objects.get(id=product_id)
            
            result = {
            "id"           : product.id,
            "name"         : product.name,
            "price"        : product.price,
            "introduction" : product.introduction,
            "description"  : product.description,
            "unit"         : product.unit,
            "shipping"     : product.shipping,
            "itemPackage"  : product.package,
            "origin"       : product.origin,
            "weight"       : product.weight,
            "images"       : product.image_set.all()[0].url
            }

            return JsonResponse({"result": result}, status=200)

        except Product.DoesNotExist:
            return JsonResponse({"message" : "INVALID_PRODUCT"}, status = 404)

path parameter로 해당 상품의 아이디값을 받음

127.0.01:8000/product/1 <<여기서 1이 product_id가 됌

해당상품을 DB에서 가져오고 해당상품을 찾지못하면

Product.DoesNotExist 발생,
"message" : "INVALID_PRODUCT" 유효하지 않은 상품이라는 메세지 반환
status = 404 리소스 없음으로 404코드 반환

문제없이 해당상품을 가져왔다면 product라는 변수에 담아 객체로 만듦

상품의 정보들을 reusult라는 딕셔너리형태의 객체에 값을 담고

result 반환, 성공적인 응답였다는것을 알려주는 200코드 반환

주문페이지 전체코드

import json, uuid
from enum import Enum

from django.http            import JsonResponse
from django.views           import View
from django.db              import transaction, DataError

from .models         import Order, OrderItem
from cart.models     import Cart
from core.decorator  import login_required

class OrderStatus(Enum):    
    WAIT_DEPOSIT       = 1   
    COMPLETION_DEPOSIT = 2    
    READY_RELEASE      = 3  
    SHIPMENT_COMPLETE  = 4
    DELIVERED          = 5
    DELAYED_DELIVERY   = 6
    DELIVERY_COMPLETED = 7
    ORDER_COMPLETE     = 8
    ORDER_CANCELLATION = 9    

class OrderView(View):
    @login_required
    def post(self, request):
        try:
            data     = json.loads(request.body)
            cart_ids = data["cart_ids"]     
            carts    = Cart.objects.filter(id__in=cart_ids,user=request.user)

            if not carts.exists():
                return JsonResponse({"message":"INVALID_CART"},status=404)
            
            with transaction.atomic():
                order = Order.objects.create(
                    order_status_id = OrderStatus.WAIT_DEPOSIT.value, 
                    users           = request.user,
                    order_number    = uuid.uuid4()
                    )
                bulk_list = [OrderItem(
                    product               = cart.product,
                    quantity              = cart.quantity,
                    order                 = order,
                    order_items_status_id = OrderStatus.WAIT_DEPOSIT.value,
                    ) for cart in carts]
                carts.delete()
                OrderItem.objects.bulk_create(bulk_list)
                
            return JsonResponse({"message":"CREATE"},status=201)
                
        except KeyError:
            return JsonResponse({"message":"KEY_ERROR"},status=400)
        except DataError:
            return JsonResponse({"message":"DATA_ERROR"},status = 400)
        except transaction.TransactionManagementError:
            return JsonResponse({"message":"TRANSACTION_ERROR"},status=400)
    
    @login_required
    def get(self, request):
            orders = Order.objects.filter(users=request.user).select_related("order_status")\
                                                             .prefetch_related("orderitem_set__product__image_set",
                                                                               "orderitem_set__order_items_status").order_by("-created_at")
           
            result=[{
                "order_id"     : order.id,
                "order_number" : order.order_number,
                "order_status" : order.order_status.status,
                "products"     : [{
                    "id"       : orderItem.product.id,
                    "name"     : orderItem.product.name,
                    "image"    : orderItem.product.image_set.all()[0].url,
                    "price"    : orderItem.product.price,
                    "quantity" : orderItem.quantity,
                    "status"   : orderItem.order_items_status.status,
                } for orderItem in order.orderitem_set.all()]
            } for order in orders]

            return JsonResponse({"result":result},status=200)

    @login_required
    def patch(self, request):
        try:
            data = json.loads(request.body)
            
            with transaction.atomic():
                order = Order.objects.get(id=data["order_id"])
                order.order_status_id = OrderStatus.ORDER_CANCELLATION.value
                order.save()
                order.orderitem_set.all().update(order_items_status=OrderStatus.ORDER_CANCELLATION.value)
        
                return JsonResponse({"message":"SUCCESS"},status=200)

        except KeyError: 
            return JsonResponse({"message":"KEY_ERROR"},status=400)
        except Order.DoesNotExist:
            return JsonResponse({"message":"INVALID_ORDER"},status=404)
        except transaction.TransactionManagementError:
            return JsonResponse({"message":"TRANSACTION_ERROR"},status=400)

주문페이지의 경우 대략적으로만 설명하겠음

  • Enum

    Enum은 서로 상관있는 상수들의 집합class이며 장고가 제공하는 라이브러리 이다.

Enum class 에서 status 숫자는 바뀌지않으며 각 상품의 결제, 배송상태를 뜻하고 있다.

  • POST

주문할 상품을 장바구니에서 가져와서 주문내역을 생성, 주문 상품 생성, 장바구니 삭제를 동시에 진행하며 transaction으로 묶음처리 해주었다.

with transaction.atomic()

with :
Python 에서 제공하는 문법이며 파일을 열었을때 구문이 끝나면 자동으로 close()해주는 특성을 가짐

transaction :
각각 쿼리를 날리는 작업단위를 묶어줌

atomic() :
transaction의 4가지 특성중 원자성을 말하며 요청이 다 성공하거나 다 실패하게끔 되며 코드 진행중 중간에 에러가 발생하거나 하면
시작하기전 세이브포인트로 롤백됌

POST요청이 잘 마무리 되었을경우

"message":"CREATE" 생성되었다는 메세지와
status=201 요청이 성공적이였으며 생성되었다는 코드인 201 반환

  • GET
Order.objects.filter(users=request.user).
	select_related("order_status").
    	prefetch_related("orderitem_set__product__image_set",
        		 "orderitem_set__order_items_status")
        	         .order_by("-created_at")

주문내역을 불러올때 한번에 가져와야 하는 테이블이 많아서
prefetch_related 와 select_related를 썼는데 이부분에 있어서는

지연로딩(LazyLoading), 즉시로딩(EagerLoading), cashing 에대해 선행학습이 되어야하며 다음 블로깅때 설명하도록 하겠다.


다시 이어서 가자면 6개 테이블에서
(order, order_item, order_status, order_items_status, product, image)

데이터를 가져와 해당 유저가 주문한 정보, 와 상품들을 프론트에게 전달

  • PATCH

해당 주문내역을 취소하면 주문내역의 status와 상품
들의 status를 주문취소로 업데이트 하기위한 코드

해당 order의 id를 프론트에게 받고 그 order를 참조하고있는 주문상품들의 status값을 모두 주문취소로 바꾸어 주었다.

profile
아자
post-custom-banner

0개의 댓글