【问题标题】:Session.request and 'Decimal' is not JSON serializableSession.request 和“十进制”不是 JSON 可序列化的
【发布时间】:2023-03-23 00:05:02
【问题描述】:

我尝试通过开发 Django 电子商务网站来提高我的 Django 知识(我是初学者)。 我想要两种类型的购物车,一种命名为购物车,另一种命名为composed_cart。 我对composed_cart 有错误。 尝试显示购物车时遇到以下错误:Object of type 'Decimal' is not JSON serializable

对于添加到composed_cart 类,我使用以下代码:

composed_cart.py:

class ComposedCart(object):
def __init__(self, request):
    self.session = request.session
    composed_cart = self.session.get('composed_cart')

    if not composed_cart:
        composed_cart = self.session['composed_cart'] = {}
    self.composed_cart = composed_cart

def add_composed(self, product, quantity=1):
    product_id = str(product.id)

    if product_id not in self.composed_cart:
        self.composed_cart[product_id] = {'quantity': 1,'price': str(product.prix_unitaire), 'tva': str(product.taux_TVA.taux_applicable)}

    else:
        self.composed_cart[product_id]['quantity'] += quantity #Ajoute +1 à la quantité et met à jour le dictionnaire contenant la quantité. += signifie ajoute à la valeur initiale de quantité.

    self.save()

def save(self):
    self.session['composed_cart'] = self.composed_cart
    self.session.modified = True


def remove(self, product): #Supprimer le produit, quelque soit la quantité.
    product_id = str(product.id)

    if product_id in self.composed_cart:
        del self.composed_cart[product_id]
    self.save()

def remove_one(self, product, quantity=1): #Méthode permettant de supprimer une unité du produit.
    product_id = str(product.id)

    if product_id in self.composed_cart: #Si le produit est dans le panier
        if self.composed_cart[product_id]['quantity'] > 1: #Et si la quantité de ce produit est supérieure à 1
            self.composed_cart[product_id]['quantity'] -= quantity #On enlève la quantité par défaut, d'est à dire 1.
        else:
            del self.composed_cart[product_id] #Si la quantité du produit est égale à 1 alors et que l'on veut enlever une unité, cela veut dire que l'on supprimer le produit.
    self.save()


def __iter__(self):

    product_ids = self.composed_cart.keys() #Sélectionne les différentes clés du dictionnaires, dans notre cas l'id du produit, la quantité, le prix.

    products = Article.objects.filter(id__in=product_ids) #On filtre sur les IDs présents dans le dictionnaire du panier.

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

    for item in self.composed_cart.values():
        item['price'] = Decimal(item['price'])
        item['tva'] = Decimal(item['tva'])
        item['total_price'] = item['price'] * item['quantity']
        item['total_item_tva'] = item['total_price'] - item['total_price'] / item['tva'] #Calcul du total de TVA par article.
        yield item

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

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

def get_total_tva(self):
    return sum(round(Decimal(item['total_item_tva']),2) for item in self.composed_cart.values()) #Calcul de la TVA, round(X,2), permet d'arrondir à 2 décimales après la virgule le montant de la TVA

def get_sub_total_price(self):
    return sum(Decimal(item['price']) * item['quantity'] for item in self.composed_cart.values()) - sum(round(Decimal(item['total_item_tva']),2) for item in self.composed_cart.values())

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

我的购物车.py:

class Cart(object):
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get('cart')

        if not cart:
            cart = self.session['cart'] = {}
        self.cart = cart

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

        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 1,'price': str(product.prix_unitaire), 'tva': str(product.taux_TVA.taux_applicable)}

        else:
            self.cart[product_id]['quantity'] += quantity #Ajoute +1 à la quantité et met à jour le dictionnaire contenant la quantité. += signifie ajoute à la valeur initiale de quantité.

        self.save()

    def save(self):
        self.session['cart'] = self.cart
        self.session.modified = True


    def remove(self, product): #Supprimer le produit, quelque soit la quantité.
        product_id = str(product.id)

        if product_id in self.cart:
            del self.cart[product_id]
        self.save()

    def remove_one(self, product, quantity=1): #Méthode permettant de supprimer une unité du produit.
        product_id = str(product.id)

        if product_id in self.cart: #Si le produit est dans le panier
            if self.cart[product_id]['quantity'] > 1: #Et si la quantité de ce produit est supérieure à 1
                self.cart[product_id]['quantity'] -= quantity #On enlève la quantité par défaut, d'est à dire 1.
            else:
                del self.cart[product_id] #Si la quantité du produit est égale à 1 alors et que l'on veut enlever une unité, cela veut dire que l'on supprimer le produit.
        self.save()


    def __iter__(self):

        product_ids = self.cart.keys() #Sélectionne les différentes clés du dictionnaires, dans notre cas l'id du produit, la quantité, le prix.

        products = Article.objects.filter(id__in=product_ids) #On filtre sur les IDs présents dans le dictionnaire du panier.

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

        for item in self.cart.values():
            item['price'] = Decimal(item['price'])
            item['tva'] = Decimal(item['tva'])
            item['total_price'] = item['price'] * item['quantity']
            item['total_item_tva'] = item['total_price'] - item['total_price'] / item['tva'] #Calcul du total de TVA par article.
            yield item

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

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

    def get_total_tva(self):
        return sum(round(Decimal(item['total_item_tva']),2) for item in self.cart.values()) #Calcul de la TVA, round(X,2), permet d'arrondir à 2 décimales après la virgule le montant de la TVA

    def get_sub_total_price(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values()) - sum(round(Decimal(item['total_item_tva']),2) for item in self.cart.values())

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

我的观点是这个添加产品:

@require_POST
def cart_add(request, product_id):
    product = get_object_or_404(Article, id=product_id)
    #Si le produit ajouté au panier est un article simple sans composition, alors on l'ajoute directement au panier.
    if product.article_composer == False:
        cart = Cart(request)
        form = CartAddProductForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            next = cd['next'] # Permet d'enregistrer la page précédente et d'y retourner une fois la quantité ajoutée dans le panier.
            cart.add(product=product, quantity=cd['quantity'])
        return HttpResponseRedirect(next) # Redirection vers la page d'où le produit a été ajouté.

    #Si l'article que l'on ajoute au panier sert à composer alors on utilise la méthode permettant de composer un article.
    else:
        composed_cart = ComposedCart(request)
        form = ComposedCartForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            next = cd['next'] # Permet d'enregistrer la page précédente et d'y retourner une fois la quantité ajoutée dans le panier.
            composed_cart.add_composed(product=product, quantity=cd['quantity'])
        return HttpResponseRedirect(next)

为了展示我的购物车:

def cart_detail(request):
    cart = Cart(request)
    composed_cart = ComposedCart(request)
    cart_product_form = CartAddProductForm()
    return render(request, 'panier/panier.html', locals())

我不明白为什么会收到 TypeError。你有什么想法?如何改进我的代码以摆脱此错误?

提前致谢

曲风

【问题讨论】:

    标签: django serialization django-forms django-sessions django-serializer


    【解决方案1】:

    我认为问题在于您发送到paneer.htmllocals()

    locals() 是当前命名空间中所有内容的字典,其中包括无法序列化的复杂对象(即转换为简单对象,例如整数或字符串)。

    为了解决这个问题,试着把它改成简单的:

    return render(request, 'panier/panier.html', {'test': 'value'})
    

    如果它有效,或者出现另一个错误,请将其更改为您需要的。

    错误表明某些字段不是 JSON 可序列化的。最简单的解决方案是这样的:

    cart = {
        'product_id': cart.product_id,
        ... 
    }
    
    composed_cart = {
        'id': composed_cart.id,
        ...
    }
    
    return render(request, 'panier/panier.html', {'cart': cart, 'composed_cart': composed_cart})
    

    也就是说,手动序列化您的对象并在模板中选择您需要的字段。

    希望对你有帮助。

    【讨论】:

    • 感谢您的回答,但我得到以下代码的相同错误:return render(request, 'panier/panier.html', {'cart': cart, 'composed_cart':composed_cart} )
    • @singertwist 你能用{'test': 'value'}试试吗?
    • 我试过 {'test': 'value'},我没有任何错误。我可以显示页面(没有任何数据)。我做了其他几个测试来试图理解这个问题。正如我上面提到的,我有两个购物车,Cart 和 Composed_Cart 这些购物车使用相同的代码,除了会话请求是: - 对于composed_cart:composed_cart = self.session['composed_cart'] - 对于购物车:cart = self .session['cart'] 当我将产品添加到 cart.py,然后将不同的产品添加到composed_cart 时,它可以工作。但是,当我只将一个产品添加到我的composed_cart 时,它不起作用(类型错误)。
    猜你喜欢
    • 1970-01-01
    • 2020-12-07
    • 2015-04-24
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多