Object of type Decimal is not JSON serializable

Tried To Follow This Issue and Still Not Solve It.
as i understood from the Error The Price in the model is a DecimalField and it is what make this Issue here.but when i change it to FloatField also i got same Error., Dont Know Why as I return context Dict in the in render function.
grateful for support guys.

Error Traceback

Traceback (most recent call last):
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/amw/.local/lib/python3.10/site-packages/django/utils/deprecation.py", line 138, in __call__
    response = self.process_response(request, response)
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/middleware.py", line 59, in process_response
    request.session.save()
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py", line 82, in save
    obj = self.create_model_instance(data)
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py", line 69, in create_model_instance
    session_data=self.encode(data),
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/base.py", line 94, in encode
    return signing.dumps(
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 150, in dumps
    return TimestampSigner(key, salt=salt).sign_object(
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 228, in sign_object
    data = serializer().dumps(obj)
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 125, in dumps
    return json.dumps(obj, separators=(",", ":")).encode("latin-1")
  File "/usr/lib/python3.10/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.10/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.10/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.10/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /orders/create/
Exception Value: Object of type Decimal is not JSON serializable

the View

def OrderCreateView(request):
    bag = Bag(request)
    if request.method == 'POST':
        order_create_form = OrderCreateForm(request.POST)
        if order_create_form.is_valid():
            order = order_create_form.save()
            for item in bag:
                OrderItem.objects.create(order=order, product=item['product'], price=item['price'], quantity=item['quantity'])
            bag.clear()  # -- Clear The Bag --
            context = {'order': order, 'page': 'Checkout'}
            return render(request, 'Orders/Order/Created.html', context)
    else:
        order_create_form = OrderCreateForm()
    context = {'bag': bag, 'order_create_form': order_create_form, 'page': 'Checkout'}
    return render(request, 'Orders/Order/Create.html', context)

model

class Order(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField()
    address = models.CharField(max_length=250)
    postal_code = models.CharField(max_length=20)
    city = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    paid = models.BooleanField(default=False)

    class Meta:
        ordering = ('-created',)

    def __str__(self):
        return f'Order {self.id}'

    def get_total_cost(self):
        return sum(item.get_cost() for item in self.items.all())


class OrderItem(models.Model):
    order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE)
    product = models.ForeignKey(Product, related_name='order_items', on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.PositiveIntegerField(default=1)

    def __str__(self):
        return str(self.id)

    def get_cost(self):
        return self.price * self.quantity

Please provide all the code of this Bag object.

Bag Object:

class Bag(object):
    def __init__(self, request):
        #   Initialize the Bag.
        self.session = request.session
        bag = self.session.get(settings.BAG_SESSION_ID)
        if not bag:
            #   save an empty Bag in the session
            bag = self.session[settings.BAG_SESSION_ID] = {}
        self.bag = bag

    def add(self, product, quantity=1, override_quantity=False):
        #   Add a product to the Bag or update its quantity.
        product_id = str(product.id)
        if product_id not in self.bag:
            self.bag[product_id] = {'quantity': 0, 'price': str(product.price)}
        if override_quantity:
            self.bag[product_id]['quantity'] = quantity
        else:
            self.bag[product_id]['quantity'] += quantity
        self.save()

    def save(self):
        self.session[settings.BAG_SESSION_ID] = self.bag
        #   mark the session as "modified" to make sure it gets saved
        self.session.modified = True

    def remove(self, product):
        #   Remove a product from the Bag.
        product_id = str(product.id)
        if product_id in self.bag:
            del self.bag[product_id]
            self.save()

    def __iter__(self):
        #   Iterate over the items in the Bag and get the products from the database.
        product_ids = self.bag.keys()
        #   get the product objects and add them to the Bag.
        products = Product.objects.filter(id__in=product_ids)
        bag = self.bag.copy()
        for product in products:
            bag[str(product.id)]['product'] = product
        for item in bag.values():
            item['price'] = Decimal(item['price'])
            item['total_price'] = item['price'] * item['quantity']
            yield item

    def __len__(self):
        #   Count all items in the Bag.
        return sum(item['quantity'] for item in self.bag.values())

    def get_total_price(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.bag.values())

    def clear(self):
        #   Remove Bag from session.
        del self.session[settings.BAG_SESSION_ID]
        self.save()

The error message posted at the top, is that the only message with a stacktrace produced? Or was there another one in your output before this one? This stacktrace doesn’t show any references to your code, so it’s not unusual for there to be a different error and stacktrace before this one. (The other, less likely probability in my mind, issue is that it could be something in the template you’re trying to render.)

1 Like

this was above the Traceback

Environment:


Request Method: POST
Request URL: http://localhost:8000/orders/create/

Django Version: 4.1.2
Python Version: 3.10.6
Installed Applications:
['Humans.apps.HumansConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'Products.apps.ProductsConfig',
 'Bags.apps.BagsConfig',
 'Orders.apps.OrdersConfig',
 'Coupons.apps.CouponsConfig',
 'Payments.apps.PaymentsConfig',
 'Webpages.apps.WebpagesConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

Error Update Now:

Environment:


Request Method: POST
Request URL: http://localhost:8000/order/create/

Django Version: 4.1.2
Python Version: 3.10.6
Installed Applications:
['Humans.apps.HumansConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'Products.apps.ProductsConfig',
 'Bags.apps.BagsConfig',
 'Orders.apps.OrdersConfig',
 'Coupons.apps.CouponsConfig',
 'Payments.apps.PaymentsConfig',
 'Webpages.apps.WebpagesConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/amw/.local/lib/python3.10/site-packages/django/utils/deprecation.py", line 138, in __call__
    response = self.process_response(request, response)
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/middleware.py", line 59, in process_response
    request.session.save()
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py", line 82, in save
    obj = self.create_model_instance(data)
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py", line 69, in create_model_instance
    session_data=self.encode(data),
  File "/home/amw/.local/lib/python3.10/site-packages/django/contrib/sessions/backends/base.py", line 94, in encode
    return signing.dumps(
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 150, in dumps
    return TimestampSigner(key, salt=salt).sign_object(
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 228, in sign_object
    data = serializer().dumps(obj)
  File "/home/amw/.local/lib/python3.10/site-packages/django/core/signing.py", line 125, in dumps
    return json.dumps(obj, separators=(",", ":")).encode("latin-1")
  File "/usr/lib/python3.10/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.10/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.10/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.10/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /order/create/
Exception Value: Object of type Product is not JSON serializable

Cart Details Template:


<div class="ui very relaxed left aligned grid container">
    <div class="sixteen wide column">
        <div class="ui breadcrumb">
            <p class="ui grey header section">Bag Details</p>
            <i class="right angle icon divider"></i>
            <p class="section">Shipping & Payment</p>
        </div>
        <div class="ui basic segment">
            <a href="{% url 'Products:CatalogListUrl' %}" class="ui button">Continue Shopping</a>
        </div>
    </div>
</div>

<div class="ui very relaxed grid container">
    <div class="column">
        <table class="ui raised segment celled table">
            <thead>
            <tr class="center aligned">
                <th>Image</th>
                <th>Name</th>
                <th>Qty</th>
                <th>Unit Price</th>
                <th>Sub Total</th>
            </tr>
            </thead>
            <tbody>
            {% for item in bag %}
            {% with product=item.product %}
            <tr class="center aligned">
                <td data-label="Image">
                    {% for img in product.images.all %}
                    {% if img.main %}
                    <a href="{{ product.get_absolute_url }}">
                        <img class="ui centered small image" src="{{ img.image.url }}" alt=""/>
                    </a>
                    {% endif %}
                    {% endfor %}
                </td>
                <td data-label="Name">
                    <a href="{{ product.get_absolute_url }}">{{ product.name }}</a>
                </td>
                <td data-label="Qty">
                    <form action="{{ product.get_add_to_bag_url }}" method="post">
                        {% csrf_token %}
                        <p>{{ item.update_quantity_form.quantity }}{{ item.update_quantity_form.override }}</p>
                        <div class="ui basic segment">
                            <input class="ui fluid button" type="submit" value="Update">
                        </div>
                    </form>
                    <form class="ui basic segment" action="{{ product.get_remove_from_bag_url }}" method="post">
                        {% csrf_token %}
                        <input class="ui fluid button" type="submit" value="Remove">
                    </form>
                </td>
                <td data-label="Unit Price">$ {{ product.price }}</td>
                <td data-label="Sub Total">$ {{ item.total_price }}</td>
            </tr>
            {% endwith %}
            {% endfor %}
            </tbody>
        </table>
    </div>
</div>

<div class="ui very relaxed grid container">

    <div class="eight wide centered aligned column">
        <a href="{% url 'Orders:OrderCreateUrl' %}" class="ui fluid button">Proceed To Checkout</a>
    </div>
</div>

Create Order Template:

<div class="ui secondary segment container">
    <h3>Your order</h3>
    <ul>
        {% for item in bag %}
        <li>
            <p>{{ item.product.name }} x {{ item.quantity }} - <span>$ {{ item.total_price }}</span></p>
        </li>
        {% endfor %}
    </ul>
    <p>Total: $ {{ bag.get_total_price }}</p>
</div>
<form method="post" class="ui form container">
    {% csrf_token %}
    {{ order_create_form.as_p }}
    <p>
        <input class="ui large green button" type="submit" value="Place order">
    </p>
</form>

So what do you think this new error message is telling you?

1 Like

I think it is about the product itself and passing it somewhere with different type.
i printed to console the bag passed to create order view

{'slug': 'elegance-circle-table-120-x-60-12369', 'name': 'Elegance Circle Table 120 x 60', 'price': '556.35', 'quantity': 3, 'product': <Product: Elegance Circle Table 120 x 60 - 12369>, 'total_price': '1669.05', 'update_quantity_form': <AddToBagForm bound=False, valid=Unknown, fields=(quantity;override)>}

Is This Considered as a valid object??

another thing i see other product object passed inside the product property inside bag, and also update_quantity_form.

Yes - more specifically, you’re trying to add an instance of the object Product to the session.

A session does not store objects, it stores serialized representations of objects. You can’t just dump any arbitrary data into your session store.

If you’re trying to save an object in a session, that object must be able to be serialized.

You might want to review the complete set of docs at How to use sessions | Django documentation | Django

1 Like