K-디지털트레이닝(빅데이터) 12일차

유현민·2021년 8월 11일
0

쿠폰 만들기

  1. python manage.py startapp coupon

  2. settings.py 앱추가

  3. 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
  1. python manage.py makemigrations coupon

  2. python manage.py migrate

  1. coupon/forms.py
from django import forms


class AddCouponForm(forms.Form):
    code = forms.CharField(label='쿠폰코드 입력')
  1. coupon/views.py
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로 넘겨라
  1. coupon/urls.py
from django.urls import path
from .views import * #대문자로 넘어오면 클래스 소문자는 메소드


app_name = 'coupon'

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




]
  1. config/urls.py
path('coupon', include('coupon.urls')),
  1. cart/cart.py
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()  # 최종 가격 표시
  1. cart/views.py
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안에서)
  1. cart/detail.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 %}
  1. coupon/admin.py
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 누르고 만들어야 된다.

profile
smilegate megaport infra

0개의 댓글