问题
I am working on e-commerce website using Django, I'm working on the shopping cart it's implemented using sessions and it's currently working fine, except one problem when the authenticated user logout from website, and login again , all data on cart lost. How can save session of shopping cart data after logout, so the user can find them when login again?
my cart app files are:
1) 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()
2) 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})
3) 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)
4) 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 %}
5) 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'),
]
@John Meinken, I faced the same problem:
How to save and restore session data across logout/relogin in Django?
and your solution may solve my problem but, can you please explain it more for me , where should I create this table? and where should I used this functions ? for example my project contine many apps (accounts, shop,cart,orders)
Thanks in advance.
来源:https://stackoverflow.com/questions/62048726/how-can-save-session-of-shopping-cart-data-after-logout-so-the-user-can-find-th