지난 시간에 이어서 coupon을 만들어보겠다.
진도가 조금 늦다고 느낄 수 있는데
현재 해커톤 준비 중이라서 시간이 여유롭지 못하다...
python manage.py startapp coupon
config/settings.py
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/forms.py
from django import forms
class AddCouponForm(forms.Form):
code = forms.CharField(label= '쿠폰 코드 입력')
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/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')),
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)
끝.
해커톤이 끝나면 좀 더 성의있게 수정해보겠다...
글 재미있게 봤습니다.