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
  • 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.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로 넘겨라
  • coupon/urls.py
  • from django.urls import path
    from .views import * #대문자로 넘어오면 클래스 소문자는 메소드
    
    
    app_name = 'coupon'
    
    urlpatterns = [
        path('add/', add_coupon, name='add'),
    
    
    
    
    ]
    
  • config/urls.py
  • path('coupon', include('coupon.urls')),
  • 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()  # 최종 가격 표시
  • 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안에서)
  • 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 %}
  • 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キーを押して作成します.