いよいよショッピングカートを作っていきます。
$ python3 manage.py startapp cart
setting.py
INSTALLED_APPS = [ 'shop', 'search', 'cart', // 省略 ] // 省略 'DIRS': [os.path.join(BASE_DIR, 'shop', 'templates/'), os.path.join(BASE_DIR, 'search', 'templates/'), os.path.join(BASE_DIR, 'cart', 'templates/')],
cart/models.py
from django.db import models from shop.models import Product class Cart(models.Model): cart_id = models.CharField(max_length=250, blank=True) date_added = models.DateField(auto_now_add=True) class Meta: db_table = 'Cart' ordering = ['date_added'] def __str__(self): return self.cart_id class CartItem(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) cart = models.ForeignKey(Cart, on_delete=models.CASCADE) quantity = models.IntegerField() active = models.BooleanField(default=True) class Meta: db_table = 'CartItem' def sub_total(self): return self.product.price * self.quantity def __str__(self): return self.product.name
$ python3 manage.py makemigrations cart
$ python3 manage.py migrate
cart/urls.py
from django.urls import path from . import views app_name = 'cart' urlpatterns = [ path('', views.cart_detail, name='cart_detail'), ]
urls.py
urlpatterns = [ path('admin/', admin.site.urls), path('shop/', include('shop.urls')), path('search/', include('search.urls')), path('cart/', include('cart.urls')), ]
cart/views.py
L session.session_keyでセッションの値を取得する
from django.shortcuts import render, redirect from .models import Cart, CartItem from django.core.exceptions import ObjectDoesNotExist def _cart_id(request): cart = request.session.session_key if not cart: cart = request.session.create() return cart def cart_detail(request, total=0, counter=0, cart_items = None): try: cart = Cart.objects.get(cart_id=_cart_id(request)) cart_items = CartItem.objects.filter(cart=cart, active=True) for cart_item in cart_items: total += (cart_item.product.price * cart_item.quantity) counter += cart_item.quantity except ObjectDoesNotExist: pass return render(request, 'cart/cart.html', dict(cart_items = cart_items, total = total, counter = counter))
cart/template/cart/cart.html
{% extends "base.html" %} {% load static %} {% block metadescription %} This is the shopping cart page.. Proceed to review your items and place the order. {% endblock %} {% block title %} Cart - Various Product Store {% endblock %} {% block content %} {% if not cart_items %} <div> <div class="text-center"> <br> <h1 class="text center my_title">Your shopping cart is empty</h1> <br> <p class="text-center"> Please click <a href="{% url 'shop:all_product' %}">here</a> to continue shopping. </p> </div> </div> {% else %} <div> <div class="text-center"> <br> <h1 class="text-center my_title"> Your shopping cart </h1> </div> <br> </div> <div class="row mx-auto"> <div class="col-12 col-sm-12 col-lg-6 text-center"> <table class="table my_custom_table"> <thread class="my_custom_thread"> <tr> <th colspan="5"> Your items </th> </tr> </thread> <tbody> {% for cart_item in cart_items %} <tr> <td><a href="cart_item.product.get_absolute_url"><img src="{{cart_item.product.image.url}}" alt="" class="float-left rounded custom_image"></a></td> <td class="text-left"> {{cart_item.product.name}} <br> SKU: {{cart_item.product.id}} <br> Unit Price: ${{cart_item.product.price}} <br> Qty: {{cart_item.quantity}} x ${{cart_item.product.price}} </td> <td> ${{cart_item.sub_total}} </td> {% if cart_item.quantity < cart_item.product.stock %} <td> <a href="{% url 'cart:add_cart' cart_item.product.id %}" class="custom_a"><i class="fas fa-plus-circle custom_icon"></i></a> <a href="" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a> <a href="" class="custom_item"><i class="far fa-trash-alt"></a> </td> {% else %} <td> <a href="" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a> <a href="" class="custom_item"><i class="far fa-trash-alt"></i></a> </td> <td></td> {% endif %} </tr> {% endfor %} </tbody> </table> </div> <div class="col-12 col-sm-12 col-lg-6 text-center"> <table class="table my_custom_table"> <thread class="my_custom_thead"> <tr> <th> Checkout </th> </tr> </thread> <tbody> <tr> <td> Please review your shopping cart item before proceeding with the order payment. </td> </tr> <tr> <td class="text-left"> Your total is: <strong>${{total}}</strong> </td> </tr> </tbody> </table> <div class="mx-auto"> <a href="{% url 'shop:all_product' %}" class="btn-secondary btn-block my_custom_button">Continue Shopping</a> </div> </div> </div> {% endif %} {% endblock %}
models.py
from shop.models import Product def add_cart(request, Product_id): product = Product.objects.get(id=product_id) try: cart = Cart.objects.get(cart_id=_cart_id(request)) except Cart.DoesNotExist: cart = Cart.objects.create( cart_id = _cart_id(request) ) cart.save() try: cart_item = CartItem.objects.get(product=product, cart=cart) cart_item.quantity += 1 cart_item.save() except CartItem.DoesNotExist: cart_item = CartItem.objects.create( product = product, quantity = 1, cart = cart ) cart_item.save() return redirect('cart:cart_detail')
urls.py
urlpatterns = [ path('add/<int:product_id>/', views.add_cart, name='add_cart'), path('', views.cart_detail, name='cart_detail'), ]
product_detail.html
<a class="btn btn-secondary" href="{% url 'cart:add_cart' product.id %}">Add to Cart</a>
cart/views.py
def cart_remove(request, product_id): cart = Cart.objects.get(cart_id=_cart_id(request)) product = get_object_or_404(Product, id=product_id) cart_item = CartItem.objects.get(product=product, cart=cart) if cart_item.quantity > 1: cart_item.quantity -= 1 cart_item.save() else: cart_item.delete() return redirect('cart:cart_detail') def full_remove(request, product_id): cart = Cart.objects.get(cart_id=_cart_id(request)) product = get_object_or_404(Product, id=product_id) cart_item = CartItem.objects.get(product=product, cart=cart) cart_item.delete() return redirect('cart:cart_detail')
urls.py
app_name = 'cart' urlpatterns = [ path('add/<int:product_id>/', views.add_cart, name='add_cart'), path('', views.cart_detail, name='cart_detail'), path('remove/<int:product_id>/', views.cart_remove, name='cart_remove'), path('full_remove/<int:product_id>/', views.full_remove, name='full_remove') ]
cart/context_processors.py
from .models import Cart, CartItem from .views import _cart_id def counter(request): item_count = 0 if 'admin' in request.path: return {} else: try: cart = Cart.objects.filter(cart_id=_cart_id(request)) cart_items = CartItem.objects.all().filter(cart=cart[:1]) for cart_item in cart_items: item_count += cart_item.quantity except Cart.DoesNotExist: item_count = 0 return dict(item_count = item_count)
settings.py
'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'cart.context_processors.counter', ],
navbar.html
{% if item_count > 0 %} <li class="nav-item"> <a class="nav-link" href="{% url 'cart:cart_detail' %}">({{item_count}})</a> </li> {% endif %}
cart.html
{% if cart_item.quantity < cart_item.product.stock %} <td> <a href="{% url 'cart:add_cart' cart_item.product.id %}" class="custom_a"><i class="fas fa-plus-circle custom_icon"></i></a> <a href="{% url 'cart:cart_remove' cart_item.product.id %}" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a> <a href="{% url 'cart:full_remove' cart_item.product.id %}" class="custom_item"><i class="far fa-trash-alt"></a> </td> {% else %} <td> <a href="{% url 'cart:cart_remove' cart_item.product.id %}" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a> <a href="{% url 'cart:full_remove' cart_item.product.id %}" class="custom_item"><i class="far fa-trash-alt"></i></a> </td> <td></td> {% endif %}
なるほど、ただこれだと、ログアウトした時の処理などが入ってないから、完成には遠いな。Libraryはないのかしら?