Aula 53 – Loja Online – Django – Decimal e Float
Aula 53 – Loja Online – Django – 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!