【问题标题】:TypeError: Object of type Decimal is not JSON serializable | DjangoTypeError:Decimal 类型的对象不是 JSON 可序列化的 |姜戈
【发布时间】:2020-11-18 20:22:38
【问题描述】:

我遇到了非常不寻常的错误。因为这个,我很困惑。当我遍历购物车项目并尝试查看它们时,它会抛出 Decimal 类型的 TypeError Object is not JSON serializable。但是,如果我从模板中删除该块,然后刷新页面并再次将相同的块添加到我的模板并刷新它可以工作的页面。我添加了一些截图。请看一下并帮助我解决这个问题

cart.py

class Cart(object):
    def __init__(self, request):
        """
        Initialize the cart
        """
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)

        if not cart:
            # save an empty cart in the session
            cart = self.session[settings.CART_SESSION_ID] = {}
        
        self.cart = cart

    def add(self, product, quantity=1, override_quantity=False):
        """
        Add a product to the cart or update its quantity
        """
        product_id = str(product.id)

        if product_id not in self.cart:
            self.cart[product_id] = {
                'quantity': 0,
                'price': str(product.price)
            }
        
        if override_quantity:
            self.cart[product_id]['quantity'] = quantity
        else:
            self.cart[product_id]['quantity'] += quantity
        
        self.save()
    def __iter__(self):
        """
        Iterate over the items in the cart
        and get the products from the database
        """
        product_ids = self.cart.keys()
        # get the product objects and add the o the cart
        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 get_total_price(self):
        """
        Calculate the total cost of the items in the cart
        """
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

orders.py

def order_create(request):
    cart = Cart(request)
    order = None
    address_form = AddressCheckoutForm()
    billing_address_id = request.session.get('billing_address_id', None)
    shipping_address_id = request.session.get('shipping_address_id', None)
    order, created = Order.objects.get_or_create(user=request.user, ordered=False)
    if shipping_address_id:
        shipping_address = Address.objects.get(id=shipping_address_id)
        order.shipping_address = shipping_address
        del request.session['shipping_address_id']
    if billing_address_id:
        billing_address = Address.objects.get(id=billing_address_id)
        order.billing_address = billing_address
        del request.session['billing_address_id']
    if billing_address_id or shipping_address_id:
        order.save()
    
    if request.method == 'POST':
        for item in cart:
            OrderItem.objects.create(
                order=order,
                product=item['product'],
                price=item['price'],
                quantity=item['quantity']
            )
        order.ordered = True
        order.save()
        cart.clear()
        return render(request, 'orders/order/created.html', {'order': order})
    return render(request, 'orders/order/create.html', {'cart': cart, 'address_form': address_form, 'object': order})     

create.html

<h1>Checkout</h1>
    {% if not object.shipping_address %}
        <h3>Shipping</h3>
        {% url "addresses:checkout_address_create" as checkout_address_create %}
        {% include 'address/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='shipping' %}
    {% elif not object.billing_address %}
        <h3>Billing</h3>
        {% url "addresses:checkout_address_create" as checkout_address_create %}
        {% include 'address/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='billing' %}
    {% else %}
        {% for item in cart %}
            {{ item.quantity }} X {{ item.product.name }}
            {{ item.total_price }}
        {% endfor %}
        <p>Total Price: {{ cart.get_total_price }}</p>
        <form action="" method="POST">
            {% csrf_token %}
            <p><input type="submit" value="Place Order"></p>
        </form>
    {% endif %}

Traceback

Internal Server Error: /order/create/
Traceback (most recent call last):
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/utils/deprecation.py", line 96, in __call__
    response = self.process_response(request, response)
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/contrib/sessions/middleware.py", line 58, in process_response
    request.session.save()
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/contrib/sessions/backends/db.py", line 83, in save
    obj = self.create_model_instance(data)
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/contrib/sessions/backends/db.py", line 70, in create_model_instance
    session_data=self.encode(data),
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/contrib/sessions/backends/base.py", line 105, in encode
    serialized = self.serializer().dumps(session_dict)
  File "/home/duke/Monday/truck-giggle/env/lib/python3.8/site-packages/django/core/signing.py", line 87, in dumps
    return json.dumps(obj, separators=(',', ':')).encode('latin-1')
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Decimal is not JSON serializable
[29/Jul/2020 14:20:17] "GET /order/create/ HTTP/1.1" 500 102125

The error

code block that is raising the error

removing the block

after removing the block and refreshing the page

adding the block again

after adding the block and refreshing the page

正如您在删除代码块之前看到的那样,在删除它并刷新页面并将代码块添加回模板并再次刷新页面之后似乎工作正常。你能帮我解决这个问题吗?

【问题讨论】:

  • 你在哪里调用了序列化程序?
  • 他没有使用任何序列化程序
  • 我这里没有使用任何序列化程序@crimsonpython24
  • @crimsonpython24 你可以查看cart.py文件中他的Cart类的__iter__方法
  • @DebopriyoDas 您是否找到解决方案或为什么会发生这种情况?我有一个类似的问题,给了我同样的错误,但我没有使用任何序列化程序。

标签: json django django-views django-templates


【解决方案1】:

这一行的问题

for product in products:
    cart[str(product.id)]['product'] = product 

产品的实例有一个十进制字段,即价格字段,它不是 JSON 可序列化的。 因此,要解决此错误,您可以将要在模板中使用的产品字段显式添加到会话数据中以进行循环。 例如:

cart[str(product.id)]['product_name'] = product.name
cart[str(product.id)]['product_price'] = float(product.price) 

对于价格字段,您可以使用浮点数,而不是将其转换为十进制:

for item in cart.values():
    item['price'] = float(item['price']) 

【讨论】:

  • 感谢您的回答。我不再在会话中保存我的购物车。我创建了一个模型。只是为了跟踪各种参数。
猜你喜欢
  • 2021-03-26
  • 2021-11-05
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 2021-07-04
  • 2021-12-10
  • 1970-01-01
相关资源
最近更新 更多