Aula 53 – Loja Online – Django – Decimal e Float

Aula 53 – Loja Online – Django – Decimal e Float

Decimal e Float

Decimal e Float

Voltar para página principal do blog

Todas as aulas desse curso

Aula 52               Aula 54

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Toti:

https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA

Backing track / Play-along:

https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA

Código Fluente

https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w

Putz!

https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw

Aula 53 – Loja Online – Django – Decimal e Float

O erro que tivemos na última aula é por causa da incompatibilidade de tipos.

O tipo decimal é uma forma mais precisa de representar um número float.

Na prática, apesar de ambos, float e decimal, representarem números decimais, eles de tipos diferentes, para o python, são dois tipos de dados distintos.

Quando você tenta fazer a algum cálculo em que você mistura tipos float e decimal, vai dá o mesmo erro que deu no nosso app.

Para que não ocorra, e você possa utilizar ambos os tipos em um mesmo cálculo, precisaremos importar o módulo Decimal.


from decimal import Decimal 
type(123.456) 
num_dec = Decimal(123.123)

num_dec + 12.45

from math import fsum

fsum([num_dec, 12.45])

No models.py do orders e do carts, temos o uso do DecimalField.

Então vamos modificar nosso e_commerce/orders/models.py para ficar assim.

e_commerce/orders/models.py


import math
from django.db import models
from django.db.models.signals import pre_save, post_save
from carts.models import Cart
from e_commerce.utils import unique_order_id_generator

ORDER_STATUS_CHOICES = (
    ('created', 'Criado'),
    ('paid', 'Pago'),
    ('shipped', 'Enviado'),
    ('refunded', 'Devolvido'),
)

class Order(models.Model):
    order_id = models.CharField(max_length = 120, blank = True)
    # billing_profile = ?
    # shipping_address = ?
    # billing_address
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null = True)
    status = models.CharField(max_length = 120, default = 'created', choices = ORDER_STATUS_CHOICES )
    shipping_total = models.DecimalField(default = 5.99, max_digits = 100, decimal_places = 2)
    total = models.DecimalField(default = 0.00, max_digits = 100, decimal_places = 2)

    def __str__(self):
        return self.order_id
    def update_total(self):
        cart_total = self.cart.total
        shipping_total = self.shipping_total
        #new_total = cart_total + shipping_total
        new_total = math.fsum([cart_total, shipping_total])
        formatted_total = format(new_total, '.2f')
        self.total = formatted_total 
        self.save()
        return new_total

def pre_save_create_order_id(sender, instance, *args, **kwargs):
    if not instance.order_id:
        instance.order_id = unique_order_id_generator(instance)

pre_save.connect(pre_save_create_order_id, sender = Order)

def post_save_cart_total(sender, instance, created, *args, **kwargs):
    if not created:
        cart_obj = instance
        cart_total = cart_obj.total
        cart_id = cart_obj.id
        qs = Order.objects.filter(cart__id=cart_id)
        if qs.count() == 1:
            order_obj = qs.first()
            order_obj.update_total()

post_save.connect(post_save_cart_total, sender=Cart)

def post_save_order(sender, instance, created, *args, **kwargs):
    print("Executando")
    if created:
        print("Atualizando")
        instance.update_total()

post_save.connect(post_save_order, sender=Order)

No models.py do carts não foi totalmente necessário, porque na soma instance.subtotal + 10, estamos somando um inteiro, e aí não dá problema, mas, se você ao invés de somar 10, somar 10.5 por exemplo, dará o mesmo erro.

e_commerce/carts/models.py  


from decimal import Decimal
from django.conf import settings
from django.db import models

from django.db.models.signals import pre_save, post_save, m2m_changed

from products.models import Product


User = settings.AUTH_USER_MODEL

class CartManager(models.Manager):
    def new_or_get(self, request):
        cart_id = request.session.get("cart_id", None)
        qs = self.get_queryset().filter(id=cart_id)
        if qs.count() == 1:
            new_obj = False
            cart_obj = qs.first()
            if request.user.is_authenticated and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
        else:
            cart_obj = Cart.objects.new(user=request.user)
            new_obj = True
            request.session['cart_id'] = cart_obj.id
        return cart_obj, new_obj

    def new(self, user=None):
        user_obj = None
        if user is not None:
            if user.is_authenticated:
                user_obj = user
        return self.model.objects.create(user=user_obj)

class Cart(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null = True, blank = True)
    products = models.ManyToManyField(Product,  blank = True)
    subtotal = models.DecimalField(default = 0.00, max_digits=100, decimal_places = 2)
    total = models.DecimalField(default = 0.00, max_digits=100, decimal_places = 2)
    updated = models.DateTimeField(auto_now = True)
    timestamp = models.DateTimeField(auto_now_add = True)

    objects = CartManager()

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

def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
  if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
    products = instance.products.all() 
    total = 0 
    for product in products: 
      total += product.price 
    if instance.subtotal != total:
      instance.subtotal = total
      instance.save()

m2m_changed.connect(m2m_changed_cart_receiver, sender = Cart.products.through)

def pre_save_cart_receiver(sender, instance, *args, **kwargs):
    if instance.subtotal > 0:
        #instance.total = instance.subtotal  + 10 # considere o 10 como uma taxa de entrega
        instance.total = Decimal(instance.subtotal) * Decimal(1.80) # 8% de taxa
    else:
        instance.total = 0.00

pre_save.connect(pre_save_cart_receiver, sender = Cart)

Agora acesse http://127.0.0.1:8000/admin e teste.

Por essa aula é só, nos vemos na próxima.

Voltar para página principal do blog

Todas as aulas desse curso

Aula 52               Aula 54

Código final da aula:

https://github.com/toticavalcanti

Outros canais

Toti:

https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA

Backing track / Play-along:

https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA

Código Fluente

https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w

Putz!

https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Nos vemos na próxima então, \o/  😉 Bons Estudos!

 

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>