我正在尝试通过使用它来创建一个电子商务网站来教自己Django。我现在在购物车上工作;它是使用Django会话实现的,它目前工作正常,但我在实现“以后保存”功能时遇到了麻烦,你可以在许多在线商店(即亚马逊或其他)上找到这些功能,允许用户从购物车中删除商品而是将它们放在允许他们从购物车页面轻松查看的列表中。在我继续之前,这是我当前购物车的views.py和cart.py:
cart.朋友:
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.朋友:
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(保存为以后的列表),然后只是将购物车类中的大部分代码复制粘贴到它上并调整它们以便简单列表,像这样的东西
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的方式有关,所以它可能是serializeable(在购物车类的添加功能中),但代码和网站工作完全正常。当我添加SFLList代码并尝试集成它时,它只会崩溃并给我错误。
我昨天花了一整天试图让我的新SFLList类工作,但无济于事。我最终放弃了更改并恢复到我最近的提交(在我创建SFLList之前以及与之相关的更改)。正如预期的那样,没有TypeError,因为Decimal只是Cart类,完全按照我在这里定义的那样定义。
我觉得必须有一个更简单的方法来做到这一点。所有“为以后保存”必须做的只是我的购物车已经做的完全相同的事情,但没有在购物车内的书。通常我会用Java或C ++这样的语言做什么,只是创建一个数组并将“Book”实例移入其中,然后迭代遍历数组并按顺序打印每本书的所有属性。这是我第一次使用像Django这样的东西,其中的东西似乎主要是通过数据库查询来完成的。它似乎我不喜欢我真的可以使用数组或列表来存储模型内的东西 - 我发现的最接近的东西叫做ArrayField,但显然它要求你的数据库是“Postgres”,我不认为我的项目正在使用(settings.py将数据库设置为sqlite3)。
最好的方法是什么?
我想你可以简单地解决这个问题,只需在你的购物车项目字典中设置一个布尔变量
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