السلام عليكم ورحمة الله وبركاته،
اقوم ببناء متجر الكتروني باستخدام Django، استخدمت sessions في عربة التسوق وهي تعمل حاليًا بشكل جيد ، باستثناء مشكلة واحدة عندما يعمل المستخدم logout من الموقع قبل عمل order ثم يقوم بتسجيل الدخول مرة أخرى ، جميع البيانات الموجودة في سلة التسوق تحذف .
كيف يمكن حفظ بيانات سلة التسوق بعد تسجيل الخروج ، بحيث يمكن للمستخدم العثور عليها عند تسجيل الدخول مرة أخرى؟
الملفات التي قمت بانشائها في cart app هي:
- cart.py
from decimal import Decimal
from django.conf import settings
from shop.models import Product
from coupons.models import Coupons
class Cart(object):
"""docstring for Cart"""
def __init__(self, request):
"""initalize the cart"""
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
self.coupon_id = self.session.get('coupon_id')
def add(self,product,quantity=1,update_quantity=False):
product_id = str(product.id)
if product_id not in self.cart:
self.cart[product_id] = {'quantity':0,'price':str(product.price)}
if update_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
self.session[settings.CART_SESSION_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 __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 __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.session.modified = True
@property
def coupon(self):
if self.coupon_id:
return Coupons.objects.get(id=self.coupon_id)
return None
def get_discount(self):
if self.coupon:
return (self.coupon.discount / Decimal('100')) * self.get_total_price()
return Decimal('0')
def get_total_price_after_discount(self):
return self.get_total_price() - self.get_discount()
- views.py
from django.shortcuts import render,redirect,get_object_or_404
from django.views.decorators.http import require_POST
from shop.models import Product
from .cart import Cart
from .forms import CartAddProductForm
from coupons.forms import CouponApplyForm
# Create your views here.
@require_POST
def cart_add(request,product_id):
cart = Cart(request)
product = get_object_or_404(Product,id=product_id)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(
product=product,
quantity=cd['quantity'],
update_quantity=cd['update']
)
return redirect('cart_detail')
def cart_remove(request,product_id):
cart = Cart(request)
product = get_object_or_404(Product,id=product_id)
cart.remove(product)
return redirect('cart_detail')
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={'quantity':item['quantity'],'update':True})
coupon_apply_form = CouponApplyForm()
return render(request,'cart_detail.html',context = {'cart':cart,'coupon_apply_form':coupon_apply_form})
- form.py
from django import forms
PRODUCT_QUANTITY_CHOICES = [(i,str(i)) for i in range(1,21)]
class CartAddProductForm(forms.Form):
# Define form fields here
quantity = forms.TypedChoiceField(choices=PRODUCT_QUANTITY_CHOICES,coerce=int)
update = forms.BooleanField(required=False,initial=False,widget=forms.HiddenInput)
- cart_detail.html
{% extends "base.html" %}
{% load static %}
{% block title_ %}
Your Shopping Cart
{% endblock title_ %}
{% block breadcrumb %}
<li class="breadcrumb-item active"><a href="{% url 'index'%}">Flowers Website</a></li>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-12 col-lg-12 col-md-12">
<table>
<thead class='t-head'>
<h1>Your Shopping Cart</h1>
<tr>
<th>Image</th>
<th>Product</th>
<th>Quantity</th>
<th>Remove</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% if cart %}
{% for item in cart %}
{% with product=item.product %}
<tr>
<td>
<a href="{{ product.get_absolute_url }}">
<img src='
{% if product.image %}
{{ product.image.url }}
{% else %}
#
{% endif %}'
width="100px">
</a>
</td>
<td>{{product.name}}</td>
<td>
<form method="post" action="{% url 'cart_add' product.id %}">
{% csrf_token %}
{{item.update_quantity_form.quantity}}
{{item.update_quantity_form.update}}
<input type="submit" value="Update">
</form>
</td>
<td>
<a href="{% url 'cart_remove' product.id%}">
Remove
</a>
</td>
<td>
{{item.price}}
</td>
<td>
{{item.total_price}}
</td>
</tr>
{% endwith %}
{% endfor %}
{% else %}
<tr>
<td colspan="4" style="width:100%;text-align:center;">there is no product !</td>
</tr>
{% endif %}
{% if cart.coupon %}
<tr class="gray">
<td>Subtotal</td>
<td colspan="4"></td>
<td class="num"> {{cart.get_total_price}}</td>
</tr>
<tr class="gray2">
{% block trans %}
{% with code=cart.coupon.code discount=cart.coupon.discount%}
<td colspan="2">"{{code}}" coupon ({{discount}})% off</td>
{% endwith %}
{% endblock trans %}
<td colspan="3"></td>
<td class="num neg"> - ${{cart.get_discount|floatformat:"2"}}</td>
</tr>
{% endif %}
<tr class="total">
<td>Total</td>
<td colspan="4"></td>
<td class="num">${{cart.get_total_price_after_discount|floatformat:"2"}}. </td>
</tr>
</tbody>
</table>
<div class="divo">
<p>
Apply a coupon
</p>
<form action="{% url 'coupon_apply' %}" method="post">
{{coupon_apply_form}}
{% csrf_token %}
<input class="btn apply-button" type="submit" value="apply" >
</form>
<p class="text-right">
<a href="{% url 'index' %}">Continu shopping</a>
<a href="{% url 'orders:order_create' %}">Checkout</a>
</p>
</div>
</div>
</div>
</div>
{% endblock content %}
- url.py
from django.urls import path
from . import views
urlpatterns=[
path('cart_detail/',views.cart_detail,name='cart_detail'),
path('add/<product_id>/',views.cart_add,name='cart_add'),
path('remove/<product_id>/',views.cart_remove,name='cart_remove'),
]