我正试图通过使用它来建立一个电子商务站点来自学Django。我现在正在购物车上。它是使用Django会话实现的,并且目前运行良好,但是我无法实现“在线保存”功能,您可以在许多在线商店(例如Amazon或其他商店)中找到该功能,以允许用户从购物车中删除商品而是将其放在一个列表中,使他们可以从购物车页面轻松查看该列表。在继续之前,这是我当前购物车的views.py和cart.py:
cart.py:
from decimal import Decimal
from django.conf import settings
from bookDetails.models import Book
# This is the cart class.
class Cart(object):
# Constructor method for the class - includes a request parameter
def __init__(self, request):
# Start by creating a session for the new cart
self.session = request.session
userCart = self.session.get(settings.CART_SESSION_ID)
if not userCart:
userCart = self.session[settings.CART_SESSION_ID] = {}
self.userCart = userCart
def save(self):
self.session.modified = True
def add(self, book, amount=1, change_amount=False):
book_id = str(book.id)
if book_id not in self.userCart:
self.userCart[book_id] = {'amount': 0,
'author': book.book_author,
'author_bio': book.author_bio,
'description': book.book_description,
'genre': book.book_genre,
'publishing_info': book.publishing_info,
'avg_rating': str(book.avg_rating),
'price': str(book.price)}
if change_amount:
self.userCart[book_id]['amount'] = amount
else:
self.userCart[book_id]['amount'] += amount
self.save()
def remove(self, book):
book_id = str(book.id)
if book_id in self.userCart:
del self.userCart[book_id]
self.save()
def __iter__(self):
book_ids = self.userCart.keys()
books = Book.objects.filter(id__in=book_ids)
cart = self.userCart.copy()
for book in books:
cart[str(book.id)]['book'] = book
for book in cart.values():
book['price'] = Decimal(book['price'])
book['total_price'] = book['price'] * book['amount']
yield book
def __len__(self):
return sum(book['amount'] for book in self.userCart.values())
def get_total_price(self):
return sum((book['price'] * book['amount']) for book in self.userCart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.save()
Views.py:
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
# This is the Book model from the bookDetails package I made.
from bookDetails.models import Book
# These are the cart and cart forms.
from .cart import Cart
from .forms import AddToCartForm
@require_POST
def addToCart(request, book_id):
userCart = Cart(request)
book = get_object_or_404(Book, id=book_id)
form = AddToCartForm(request.POST)
if form.is_valid():
data = form.cleaned_data
userCart.add(book=book,
amount=data['amount'],
change_amount=data['change_amount'])
return redirect('cart:cart_info')
def removeFromCart(request, book_id):
userCart = Cart(request)
book = get_object_or_404(Book, id=book_id)
userCart.remove(book)
return redirect('cart:cart_info')
def cart_info(request):
userCart = Cart(request)
for current in userCart:
current['update_amount_form'] = AddToCartForm(
initial={'amount': current['amount'],
'change_amount': True}
)
return render(request, 'cart/info.html', {'userCart': userCart})
# This view displays the checkout page
def checkout(request):
userCart = Cart(request)
userCart.clear()
return render(request, 'cart/checkout.html', {'userCart': userCart})
因此,按照我设置购物车的方式,设置“稍后保存”功能的最简单/最有效的方法是什么?我最初试图做的是创建另一个与Cart类类似的类,除了它称为SFLList(保存为以后的列表),然后将大部分代码从cart类复制粘贴到该类上,并对其进行了简单的调整。列表,像这样
class SFLList(object):
def __init__(self, request):
self.session = request.session
SFL = self.session.get(settings.SFL_SESSION_ID)
if not SFL:
SFL = self.session[settings.SFL_SESSION_ID] = {}
self.SFL = SFL
# Below this would go functions like addSFL, removeSFL,
# and the __iter__ function, all redefined to work with SFLList
...但是这最终给了我TypeError的错误,因为“ Decimal类型不可JSON序列化”或类似的结果,这似乎与我将price属性转换为str的方式有关。它可能是可序列化的(在cart类的add函数中),但是代码和站点可以按原样完美工作。当我添加SFLList代码并尝试对其进行集成时,它只是崩溃了,并给了我那个错误。
昨天我整天都在努力使新的SFLList类正常工作,但无济于事。我最终只是放弃所做的更改并恢复到我的最新提交(在创建SFLList和与之相关的更改之前)。不出所料,当它只是Cart类时,就不会因为Decimal而出现TypeError了,完全按照我在这里定义的那样。
我觉得必须有一种更简单的方法来做到这一点。 “为以后保存”所要做的只是我的购物车已经做的完全相同的事情,但是没有将书放在购物车中。通常,我会用Java或C ++之类的语言执行操作,或者只是创建一个数组并将“ Book”实例移入其中,然后遍历该数组并按顺序打印每本书的所有属性。这是我第一次使用Django之类的工具,其中大部分事情似乎都是通过数据库查询完成的。似乎我不喜欢真正使用数组或列表在模型中存储东西-我发现最接近的东西叫ArrayField,但显然它要求您的数据库为“ Postgres”,我认为这不是我的项目正在使用(settings.py的数据库设置为sqlite3)。
最好的方法是什么?
答案 0 :(得分:1)
我想您可以像这样在购物车词典中设置布尔变量来简化问题
self.userCart[book_id] = {
'amount': 0,
'author': book.book_author,
'author_bio': book.author_bio,
'description': book.book_description,
'genre': book.book_genre,
'publishing_info': book.publishing_info,
'avg_rating': str(book.avg_rating),
'price': str(book.price),
'for_later': False # saved for later if True
}
如果您只想要购物车中的书,则可以:
def get_books_ids(self):
books_ids = []
for key, val in self.userCart.items():
if not val['for_later']:
books_ids.append(key)
return books_ids
def __iter__(self):
book_ids = self.get_books_ids()
books = Book.objects.filter(id__in=book_ids)
cart = self.userCart.copy()
for book in books:
cart[str(book.id)]['book'] = book
for book in cart.values():
book['price'] = Decimal(book['price'])
book['total_price'] = book['price'] * book['amount']
yield book