注销后如何保存购物车数据的会话,以便用户在 Django 中再次登录时可以找到它们?
Posted
技术标签:
【中文标题】注销后如何保存购物车数据的会话,以便用户在 Django 中再次登录时可以找到它们?【英文标题】:How can save session of shopping cart data after logout, so the user can find them when login again in Django? 【发布时间】:2020-09-14 19:48:30 【问题描述】:我正在使用 Django 开发电子商务网站,我正在开发使用会话实现的购物车,目前工作正常,除了经过身份验证的用户从网站注销并再次登录时出现问题,所有数据都在购物车丢失。 退出后如何保存session的购物车数据,方便用户再次登录时找到?
我的购物车应用文件是:
1) 购物车.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) 表单.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 %'
>
</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,我也遇到了同样的问题:
How to save and restore session data across logout/relogin in Django?
您的解决方案可能会解决我的问题,但是,您能否为我解释一下,我应该在哪里创建此表?我应该在哪里使用这个功能?例如我的项目包含许多应用程序(帐户、商店、购物车、订单)
提前致谢。
【问题讨论】:
【参考方案1】:我遇到了同样的问题并通过以下程序解决了它: 您可以保留当前购物车的深层副本,并在注销后将其设置为会话,如下所示:
import copy
from django.contrib.auth import logout
def logout_user(request):
cart = copy.deepcopy(Cart(request).cart)
logout(request)
session = request.session
session[settings.CART_SESSION_ID] = cart
session.modified = True
return redirect('login')
【讨论】:
以上是关于注销后如何保存购物车数据的会话,以便用户在 Django 中再次登录时可以找到它们?的主要内容,如果未能解决你的问题,请参考以下文章