Захотел сделать корзину и избранное на основе сессии.
Когда я сделал избранное, я начал получать странные ошибки:
TypeError at /cart/
Object of type Decimal is not JSON serializable
Request Method: GET
Request URL: http://127.0.0.1:8000/cart/
Django Version: 4.0.4
Exception Type: TypeError
Exception Value:
Object of type Decimal is not JSON serializable
Но проблема не в том, о чем пишет ошибка: На самом деле он просто не может сериализовать пустое поле:
allow_nan
True
check_circular
True
cls
<class 'json.encoder.JSONEncoder'>
default
None
ensure_ascii
True
indent
None
kw
{}
obj
{'cart': {'2': {'price': Decimal('123123.12'),
'product': <Product: test1>,
'quantity': 2,
'total_price': Decimal('246246.24'),
'update_quantity_form': <CartAddProductForm bound=False, valid=Unknown, fields=(quantity;update)>}},
'favorites': {}}
separators
(',', ':')
skipkeys
False
sort_keys
False
Как, например, тут, пустое "Избранное". И притом, если товары будут одновременно и в избранном, и в корзине, то все будет нормально.
Код корзины:
from decimal import Decimal
from django.conf import settings
from main.models import Product
class Cart(object):
def __init__(self, request):
"""
Инициализация корзины
"""
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
def __iter__(self):
"""
Перебираем товары в корзине и получаем товары из базы данных.
"""
product_ids = self.cart.keys()
# получаем товары и добавляем их в корзину
products = Product.objects.filter(id__in=product_ids)
cart = self.cart.copy()
for product in products:
cart[str(product.id)]['product'] = product
for item in 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 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
if quantity == 0:
del self.cart[product_id]
self.save()
def save(self):
# сохраняем товар
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 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.save()
Код Избранного:
from django.conf import settings
from main.models import Product
class Favorites(object):
def __init__(self, request):
self.session = request.session
favorites = self.session.get(settings.FAVORITES_SESSION_ID)
if not favorites:
favorites = self.session[settings.FAVORITES_SESSION_ID] = {}
self.favorites = favorites
def __len__(self):
Fsum = 0
for item in self.favorites.values():
Fsum += 1
return Fsum
def __iter__(self):
product_ids = self.favorites.keys()
products = Product.objects.filter(id__in=product_ids)
favorites = self.favorites.copy()
for product in products:
favorites[str(product.id)]['product'] = product
for item in favorites.values():
yield item
def remove(self, product):
product_id = str(product.id)
if product_id in self.favorites:
del self.favorites[product_id]
self.save()
def add(self, product):
product_id = str(product.id)
if product_id not in self.favorites:
self.favorites[product_id] = {'product_id': product_id}
else:
del self.favorites[product_id]
self.save()
def save(self):
self.session.modified = True
def clear(self):
del self.session[settings.FAVORITES_SESSION_ID]
self.save()
Как тут видно, я использовал разные SESSION_ID.
Вопрос: Как сделать так, чтобы и корзина, и избранное, могли работать независимо друг от друга?