[멋사] OnlineShpping - 쿠폰

김지연·2023년 8월 5일
1

멋쟁이사자처럼_hywu

목록 보기
16/17

지난 시간에 이어서 coupon을 만들어보겠다.
진도가 조금 늦다고 느낄 수 있는데
현재 해커톤 준비 중이라서 시간이 여유롭지 못하다...

Coupon

coupon 앱 생성

python manage.py startapp coupon

config/settings.py


coupon - model

coupon/models.py

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

# Create your models here.
# 쿠폰

class Coupon(models.Model) :
    code = models.CharField(max_length=50, unique=True)
    use_from = models.DateTimeField()
    use_to = models.DateTimeField()
  	# min max 값을 지정해준다. (0~100000) 
    amount = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100000)])
    active = models.BooleanField()

    def __str__(self):
        return self.code

모델 생성을 했으니 DB에 반영을 하자...

python manage.py makemigrations coupon
python manage.py migrate

모델도 만들었으니 장바구니에서 사용할 수 있게 Cart 클래스를 수정하자.
수정한 부분은 위에 표시를 했다...

cart/cart.py

from decimal import Decimal
## 수정한 부분
from coupon.models import Coupon

import requests

from django.conf import settings
from shop.models import Product



class Cart(object):
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get(settings.CART_ID) # settings에 CART_ID와 연결
        ## 수정한 부분
        if not cart : # cart 정보가 없으면
            cart = self.session[settings.CART_ID] = {} # 새 딕셔너리 생성
        self.cart = cart
        self.coupon_id = self.session.get('coupon_id')

    def __len__(self): # 장바구니에 있는 상품의 수량을 전부 더한 결과
        return sum(item['quantity'] for item in self.cart.values())

    def __iter__(self): # for문 사용시 어떤 요소를 건내줄지 지정
        product_ids = self.cart.keys() # 제품 번호 목록을 가져옴

        products = Product.objects.filter(id__in=product_ids) # 장바구니에 있는 제품 정보만 Product db에서 가져옴

        for product in products: # 제품 정보를 하나씩 읽어와서
            self.cart[str(product.id)]['product'] = product # session에 키 값들을 넣을 때 문자로 넣는다

        for item in self.cart.values(): # 장바구니에 있는 제품을 하나씩 꺼내
            item['total_price'] = item['price'] * item['quantity'] # 가격 x item 수를 총 가격에 넣고
            item['price'] = Decimal(item['price']) # 가격에 숫자형으로 바꿔 item에 넣는다

            yield item

    # 장바구니에 넣기
    def add(self, product, quantity=1, is_update=False): # 제품 정보를 업데이트하는지 아닌지 확인
        product_id = str(product.id)
        if product_id not in self.cart:
            self.cart[product_id] = {'quantity':0, 'price':str(product.price)}

        if is_update:
            self.cart[product_id]['quantity'] = quantity
        else:
            self.cart[product_id]['quantity'] += quantity
        self.save()

    # 장바구니 저장하기
    def save(self):
        self.session[settings.CART_ID] = self.cart
        self.session.modified = True

    # 장바구니에서 삭제하기
    def remove(self, product):
        product_id = str(product.id)
        if product_id in self.cart: # 장바구니에 제품이 있다면
            del(self.cart[product_id]) # 해당하는 제품을 삭제하고
            self.save() # 현재 장바구니를 저장한다

    ## 수정한 부분
    # 장바구니 비우기
    def clear(self):
        self.session[settings.CART_ID] = {}
        self.session.modified = True
        self.session['coupon_id'] = None # 쿠폰 추가

    # 장바구니에 있는 제품의 총 가격 계산
    def get_product_total(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

coupon - form

coupon/forms.py

from django import forms

class AddCouponForm(forms.Form):
    code = forms.CharField(label= '쿠폰 코드 입력')

coupon - view

coupon/views.py

from django.shortcuts import render, redirect
from django.utils import timezone
from django.views.decorators.http import require_POST

from .models import Coupon
from .forms import AddCouponForm

# Create your views here.
# 쿠폰 추가 뷰
@require_POST
def add_coupon(request):
    now = timezone.now()
    form = AddCouponForm(request.POST)
    if form.is_valid():
        code = form.cleaned_data['code']

        try:
            coupon = Coupon.objects.get(code__iexact=code, use_from__lte=now,
                                        use_to__gte=now, active=True)
            request.session['coupon_id'] = coupon.id
        except Coupon.DoesNotExist:
            request.session['coupon_id'] = None
    return redirect('cart:detail')

coupon - url

coupon/urls.py

from django.urls import path
from .views import add_coupon

app_name = 'coupon'

urlpatterns = [
    path('add/', add_coupon, name='add')
]

config/urls.py

path('coupon/', include('coupon.urls')),

coupon

cart/cart.py

@property
    def coupon(self):
        if self.coupon_id:
            return Coupon.objects.get(id=self.coupon_id)
        return None
    def get_discount_total(self):
        if self.coupon:
            if self.get_product_total() >= self.coupon.amount:
                return self.coupon.amount
        return Decimal(0)
    def get_total_price(self):
        return self.get_product_total() - self.get_discount_total()

@property를 사용해서 코드를 좀 더 간결하고 읽기 편하게 작성한다.

cart/views.py

def detail(request):
    cart = Cart(request)
    ## 수정
    add_coupon = AddCouponForm()

    for product in cart :
        product['quantity_form'] = AddProductForm(initial={'quantity':product['quantity'], 'is_update':True})
    return render(request, 'cart/detail.html', {'cart':cart, 'add_coupon':add_coupon})

cart/detail.html 추가 (위치는 table태그 끝나고 바로 붙인다)

<p>
사용 쿠폰 :
</p>
<form action="{% url 'coupon:add' %}" method = "post">
{{add_coupon}}
<input class="btn btn-outline-info" type="submit" value = "사용">
{% csrf_token %}
</form>

coupon/admin.py (관리자만 등록한다)

from django.contrib import admin
from .models import Coupon
# Register your models here.

class CouponAdmin(admin.ModelAdmin) :
    list_display = ['code', 'use_from', 'use_to', 'amount', 'active']
    list_filter = ['active', 'use_from', 'use_to']
    search_fields = ['code']

admin.site.register(Coupon, CouponAdmin)

끝.

해커톤이 끝나면 좀 더 성의있게 수정해보겠다...

profile
천천히 꾸준히 하는 블로그

3개의 댓글

comment-user-thumbnail
2023년 8월 5일

글 재미있게 봤습니다.

답글 달기
comment-user-thumbnail
2023년 8월 7일

너무 재미있고 유익한 내용인데 다음편은 없나요?

1개의 답글