I got an error:
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
The fact is that I store my favorites and the basket in the same session, and when one of these is not filled (favorites / basket), this error appears. When the products are in both lists everything is fine.
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
If I add product in favorites and remove items from the cart, I already get this error
TypeError at /favorites/
Object of type Product is not JSON serializable
Request Method: GET
Request URL: http://127.0.0.1:8000/favorites/
Django Version: 4.0.4
Exception Type: TypeError
Exception Value:
Object of type Product is not JSON serializable
Exception Location: E:\Python\lib\json\encoder.py, line 179, in default
There is the cart code:
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()
cart/views.py:
import datetime
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from main.models import Product, OrderItems, Order
from .cart import Cart
from .forms import CartAddProductForm, OrderForm
@require_POST
def cart_add(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
form = CartAddProductForm(request.POST)
cd = form.cleaned_data
cart.add(product=product,
quantity=1,
update_quantity=cd['update'])
return redirect('cart: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:cart_detail')
def cart_detail(request):
form = OrderForm()
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={'quantity': item['quantity'],
'update': True})
if request.method == 'POST':
data = Order(data_time=datetime.date.today(),
user=request.user.username,
total_cost=cart.get_total_price())
form = OrderForm(request.POST, instance=data)
if form.is_valid():
order = form.save()
data.save()
for item in cart:
OrderItems.objects.create(Order=order,
Product=item['product'],
Price=item['price'],
Quantity=item['quantity'])
cart.clear()
return redirect('home')
return render(request, 'main/cart.html', {'cart': cart, 'form': form})
cart/urls.py:
from django.urls import path
from . import views
app_name = 'cart'
urlpatterns = [
path('', views.cart_detail, name='cart_detail'),
path('add/<int:product_id>/',
views.cart_add,
name='cart_add'),
path('remove/<int:product_id>/',
views.cart_remove,
name='cart_remove'),
]
Favorites are same, but with no quantity and price:
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] = {}
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()
views.py and urls.py are the same as in the cart
I also used different SESSION_ID for each
And i have context_processors.py:
from .cart import Cart
def cart(request):
return {'cart': Cart(request)}
favorites context processors are the same
This is how I display them:
<div class="catalog__wrap">
<div class="catalog__items items" itemscope="" itemtype="https://schema.org/ItemList">
{% for item in featured %}
{% with product=item.product %}
<div class="item" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/Product" data-element-id="21977">
<img class="item__img" itemprop="image" src="{{ product.multiple_images.first.images.url}}" alt="{{ product.name }}">
<div class="item__info">
<h3 class="item__name">{{ product.name }}</h3>
<div class="item__offers" itemprop="offers" itemscope="" itemtype="https://schema.org/Offer">
<p class="item__price item__price">
Опт <span class="item__sum" itemprop="price">{{ product.price }} ₽</span>
</p>
<p class="item__price item__price--red">
Розница <span class="item__sum" itemprop="price">{{ product.price }} ₽</span>
</p>
</div>
<div class="item__buttons">
<form action="{% url 'cart:cart_add' product.id %}" method="post">
<button class="item__buy" type="submit" data-modal="sizes" style="width: 95px; height: 40px">В корзину</button>
{% csrf_token %}
</form>
</button>
</div>
</div>
<a class="item__link" itemprop="url" href="{% url 'product_page' product.cat.slug product.slug %}" title="{{ product.name }}"></a>
</div>
{% endwith %}
{% endfor %}
</div>
How can i fix it?
use
return render(request, 'main/cart.html', {'cart': json.dumps(cart,cls=DjangoJsonEncoder), 'form': form})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.