Session.request和'Decimal'不是JSON可序列化的

时间:2018-02-10 08:22:52

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

我尝试通过开发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

我的cart.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。你有什么想法?如何改进我的代码以消除此错误?

提前致谢

Singertwist

1 个答案:

答案 0 :(得分:3)

我认为您发送到locals()的问题是paneer.html

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})

即,手动序列化对象并选择模板中需要的字段。

希望它有所帮助。