【问题标题】:TypeError: Object of type 'Product' is not JSON serializableTypeError:“产品”类型的对象不是 JSON 可序列化的
【发布时间】:2021-10-27 00:01:44
【问题描述】:

我正在创建一个无需任何注册即可处理购物的商店,但我遇到了一些问题。

我正在存储有关用户在 django 会话中添加到购物篮的产品的数据,并且我正在尝试创建类似的系统来存储用户已完成的订单。

这是在所有付款完成后执行的视图:

#I am not pasting the imports, all fine with them

basket = Basket(request)
orders = Orders(request)

### We are looping through the all items we are storing in basket to create for each one, single order
for basketitem in basket:
    #This order is automatically created for admin, just ignore it, it's working fine
    order = Order.objects.create(user_id=user_id, product=basketitem['product'], size=basketitem['size'], quantity=basketitem['quantity'], full_name=full_name, address1=address1,
                                 address2=address2, postcode=postcode, town=town, country=country, total_paid=baskettotal, order_key=order_key, authenticated=False)

    #This is the main problem, this is trying to get a product from database "Product" comparing id from database to id that we store in basket in django sessions
    product = get_object_or_404(
        Product, id=int(basketitem['productid']))

    orders.add(product=product, quantity=basketitem['quantity'], size=basketitem['size'], full_name=full_name, address1=address1,
               address2=address2, postcode=postcode, town=town, country=country, created=now.strftime("%d/%m/%Y %H:%M:%S"))

然后出现错误“'Product' 类型的对象不是 JSON 可序列化的”

完整的追溯:

Internal Server Error: /orders/add/
Traceback (most recent call last):
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\utils\deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\contrib\sessions\middleware.py", line 61, in process_response
    request.session.save()
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\contrib\sessions\backends\db.py", line 83, in save
    obj = self.create_model_instance(data)
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\contrib\sessions\backends\db.py", line 70, in create_model_instance
    session_data=self.encode(data),
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\contrib\sessions\backends\base.py", line 116, in encode
    compress=True,
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\core\signing.py", line 110, in dumps
    return TimestampSigner(key, salt=salt).sign_object(obj, serializer=serializer, compress=compress)
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\core\signing.py", line 172, in sign_object
    data = serializer().dumps(obj)
  File "D:\GitHub\Ecommerce-Store\venv\lib\site-packages\django\core\signing.py", line 87, in dumps
    return json.dumps(obj, separators=(',', ':')).encode('latin-1')
  File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'Product' is not JSON serializable

Basket.py

class Basket():
    def __init__(self, request):
        self.session = request.session
        basket = self.session.get('bt')
        if 'bt' not in request.session:
            basket = self.session['bt'] = {}
        self.basket = basket

    def add(self, product, quantity, size):
        product_id = str(product.id)

        if product_id not in self.basket:
            self.basket[product_id] = {'productid': int(product.id), 'price': int(
                product.price), 'quantity': int(quantity), 'size': int(size)}

        self.session.modified = True

Orders.py

from decimal import Decimal

from store.models import Product


class Orders():
    def __init__(self, request):
        self.session = request.session
        orders = self.session.get('os')
        if 'os' not in request.session:
            orders = self.session['os'] = {}
        self.orders = orders

    def add(self, product, quantity, size, full_name, address1, address2, postcode, town, country, created):
        product_id = str(product.id)

        if product_id not in self.orders:
            self.orders[product_id] = {'price': int(
                product.price), 'quantity': int(quantity), 'size': int(size), 'full_name': str(full_name),
                'address1': str(address1), 'address2': str(address2), 'postcode': str(postcode), 'town': str(town),
                'country': str(country), 'created': str(created)
            }

        self.session.modified = True

    def delete(self, product):
        product_id = str(product)

        if product_id in self.orders:
            del self.orders[product_id]

        self.session.modified = True

    def clear(self):
        del self.session['os']
        self.session.modified = True

    def __iter__(self):
        product_ids = self.orders.keys()
        products = Product.products.filter(id__in=product_ids)
        orders = self.orders.copy()

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

        for item in orders.values():
            item['price'] = float(item['price'])
            item['total_price'] = item['price'] * item['quantity']
            yield item

    def __len__(self):
        return sum(item['quantity'] for item in self.orders.values())

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

我想知道为什么执行的类似操作不会抛出相同的错误

def basket_add(request):
    '''
    Handles data captured from ajax and adds product to basket,
    updates the actual amount of products in basket.
    '''
    basket = Basket(request)
    if request.POST.get('action') == 'post':
        product_id = int(request.POST.get('productid'))
        quantity = int(request.POST.get('quantity'))
        size = int(request.POST.get('size'))
        product = get_object_or_404(Product, id=product_id)
        basket.add(product=product, quantity=quantity, size=size)
        basket_quantity = basket.__len__()
        response = JsonResponse({'quantity': basket_quantity})
        return response

有什么解决办法吗?

【问题讨论】:

  • 什么是Product?这是一个关于序列化这个对象的问题,而大多数其他代码可能是不相关的。这将有助于显示回溯,以便我们准确了解失败的原因。
  • @tdelaney 抱歉,请稍等
  • 你能分享整个回溯吗?
  • 好的,等一下@bdbd
  • 我不知道解决方案,但这里有一个关于 django 序列化的链接:docs.djangoproject.com/en/3.2/topics/serialization

标签: python json django django-sessions


【解决方案1】:

您提到的错误是从 json encode default 方法引发的。这意味着 json 模块无法识别 Product 对象。 Django 内置序列化机制,可以将模型对象序列化为 JSON 对象。

如果你不想使用Django的方式来序列化数据,你可能需要定义一个自定义的编码器[1]来处理Product对象。

[1]https://docs.python.org/3/library/json.html#encoders-and-decoders

【讨论】:

    猜你喜欢
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2019-11-21
    • 2021-11-13
    • 2018-09-22
    • 2019-01-17
    • 2019-12-07
    相关资源
    最近更新 更多