K-Digital Training(ビッグデータ)12日目
25502 ワード
クーポンの作成
python manage.py startapp coupon
settings.pyアプリケーションの追加
coupon/models.py
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
class Coupon(models.Model):
code = models.CharField(max_length=50, unique=True)#유니크는 중복안되게해준다
use_from = models.DateTimeField()#유효기간
use_to = models.DateTimeField()
amount = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100000)])#쿠폰 금액 한계
activate = models.BooleanField()
def __str__(self):
return self.code
python manage.py makemigrations coupon
python manage.py migrate
from django import forms
class AddCouponForm(forms.Form):
code = forms.CharField(label='쿠폰코드 입력')
from django.shortcuts import render, redirect
from django.views.decorators.http import require_POST
from django.utils import timezone # 시간 가져오기
from .models import *
from .forms import AddCouponForm
@require_POST
def add_coupon(request): # 쿠폰 추가(user가 쿠폰번호 입력하고 쓰겠다고 할 때 호출)
now = timezone.now() # 쓰는시간 알아내기
form = AddCouponForm(request.POST) # 폼에 값이 들어오게된다
if form.is_valid(): # 값이 있으면
code = form.cleaned_data['code'] # 코드로 초기화
try:
coupon = Coupon.objects.get(code__iesact=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')#앱네임을 cart라고 해놨다. cart의 detail로 넘겨라
from django.urls import path
from .views import * #대문자로 넘어오면 클래스 소문자는 메소드
app_name = 'coupon'
urlpatterns = [
path('add/', add_coupon, name='add'),
]
path('coupon', include('coupon.urls')),
from decimal import Decimal
from django.conf import settings
from shop.models import Product
from coupon.models import Coupon
class Cart(object):
def __init__(self, request):
self.session = request.session
cart = self.session.get(settings.CART_ID) # config/settings.에 있는 session id를 cart에서 호출이되면 쓰겠다.
if not 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):
product_ids = self.cart.keys() # 카트에있는 각각 키값
products = Product.objects.filter(id__in=product_ids)
for product in products: # 있는것만큼 카트에 담아라
self.cart[str(product.id)]['product'] = product
# 데이터 베이스에 있는 목록중 카트에 담기로한 제품 목록을 하나씩 가지고 와서 로컬에 담고 그 담은걸 그냥 못쓰니까 세션에 담기(카트에 담기)
for item in self.cart.values():
item['price'] = Decimal(item['price']) # 객체형태로 만드는것
item['total_price'] = item['price'] * item['quantity']
yield item
def add(self, product, quantity=1, is_update=False): # 1은 default값이다. 값이 없으면 한개이다.
product_id = str(product.id)
if product_id not in self.cart: # pro아이디가 없으면
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 not 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())
@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) # 계산식 위에 있음 쿠폰없으면 0을 넘겨준다. 있으면 쿠폰값 넘겨줌
def get_total_price(self):
return self.get_product_total() - self.get_discount_total() # 최종 가격 표시
from coupon.forms import AddCouponForm #앱을가져온다
def detail(request):
cart = Cart(request)
add_coupon = AddCouponForm()
for product in cart:
product['quantity_form'] = AddProductForm(initial={ # add를 실행할때 받을값
'quantity': product['quantity'], 'is_update': True
})
return render(request, 'cart/detail.html', {'cart': cart, 'add_coupon': add_coupon})
# ''안에있는건 이런 이름으로 쓰겠다는 뜻(html안에서)
{% extends 'base.html' %}
{% block title %}
CartList
{% endblock %}
{% block content %}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Image</th>
<th scope="col">Product</th>
<th scope="col">Quantity</th>
<th scope="col">Remove</th>
<th scope="col">UnitPrice</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
{% for item in cart %}
{% with product=item.product %}
<tr>
<th scope="row">
<a href="{{product.get_absolute_url}}">
<img src="{{product.image.url}}" class="img-thumbnail">
</a>
</th>
<td>{{product.name}}</td>
<td>
<form action="{% url 'cart:product_add' product.id %}" method="post">
{% csrf_token %}
{{item.quantity_form.quantity}}
{{item.quantity_form.is_update}}
<input type="submit" class="btn btn-primary" value="Update">
</form>
</td>
<td><a href="{% url 'cart:product_remove' product.id%}">Remove</a></td>
<td class="num">{{item.price}}</td>
<td class="num">{{item.total_price}}</td>
</tr>
{% endwith %}
{% endfor %}
{% if cart.coupon %}
<tr class="total">
<td>Subtotal</td>
<td colspan="4"></td>
<td class="num">{{cart.get_product_total|floatformat:"2"}}</td>
</tr>
<tr>
<td>{{cart.coupon.code}} coupon ({{cart.coupon.amount}})</td>
<td colspan="4"></td>
<td>- {{cart.get_discount_total|floatformat:"2"}}</td>
</tr>
{% endif %}
<tr class="total">
<td>Total</td>
<td colspan="4"></td>
<td class="num">{{cart.get_total_price|floatformat:"2"}}</td>
</tr>
</tbody>
</table>
<p>
Add Coupon:
</p>
<form action="{% url 'coupon:add' %}" method="post">
{% csrf_token %}
{{add_coupon}}
<input type="submit" value="Add">
</form>
{% endblock %}
from django.contrib import admin
from .models import Coupon
class CouponAdmin(admin.ModelAdmin):
list_display = ['code', 'use_from', 'use_to', 'amount', 'activate']
list_filter = ['activate', 'use', 'use_from', 'use_to']
search_fields = ['code']
admin.site.register(Coupon, CouponAdmin)
クーポンはactivateキーを押して作成します.Reference
この問題について(K-Digital Training(ビッグデータ)12日目), 我々は、より多くの情報をここで見つけました https://velog.io/@y7y1h13/K-디지털트레이닝빅데이터-12일차テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol