如何在注销后保存购物车的会话数据,以便用户再次登录Django时可以找到它们?

问题描述

我使用Django在电子商务网站上工作,我在购物车上工作,它是使用会话实现的,目前运行正常,除了一个问题,当经过身份验证的用户从网站注销并再次登录时,购物车上的所有数据都会丢失。 如何在注销后保存购物车数据的会话,以便用户再次登录时可以找到它们?

我的购物车应用程序文件是:

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,我面临着同样的问题:

How to save and restore session data across logout/relogin in Django?

您的解决方案可能会解决我的问题,但是,您能为我解释一下吗,我应该在哪里创建这个表?我应该在哪里使用这些函数?例如,我的项目包含许多应用程序(帐户、商店、购物车、订单)

提前谢谢。


解决方案

我也遇到过同样的问题,解决方法如下: 您可以保留当前购物车的深层副本,并在注销后将其设置为会话,如下所示:

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')

相关文章