Aula 43 – Loja Online – Django – Carrinho – Cálculo do Total

Aula 43 – Loja Online – Django – Carrinho – Cálculo do Total

Cálculo do Total

Cálculo do Total

Voltar para página principal do blog

Todas as aulas desse curso

Aula 42               Aula 44

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

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 43 – Loja Online – Django – Carrinho – Cálculo do Total

Nessa aula vamos implementar o cálculo do total do carrinho.

Abra a django_ecommerce/carts/views.py para começarmos.

django_ecommerce/carts/views.py


from django.shortcuts import render
from .models import Cart

def cart_home(request):
  cart_obj, new_obj = Cart.objects.new_or_get(request)
  products = cart_obj.products.all()
  total = 0
  for product in products:
    total += product.price
  print(total)
  cart_obj.total = total
  cart_obj.save()
  return render(request, "carts/home.html", {})

Abra a página de admin para testar.

127.0.0.1:8000/admin/carts/

Para criar o total de forma mais eficiente e funcional, vamos usar signals.

Já usamos signals no gerador de slug dos produtos, no arquivo models.py do products.

No caso do total, será um pouco diferente, porque temos os produtos que tem relacionamento de muitos para muitos.

Mas, o que são signals e para que servem?

O Django inclui um “despachante de sinal” que ajuda no desacoplamento dos aplicativos, permitindo que determidas partes da aplicação sejam notificadas quando ações ocorrerem em outro lugar da mesma aplicação.

Resumindo, os sinais permitem que certos remetentes notifiquem um conjunto de receptores de que alguma ação ocorreu, é o famoso listener do padrão de projetos Observer.

Eles são especialmente úteis quando muitos trechos de código podem estar interessados nos mesmos eventos.

Essencialmente, eles permitem que você envie um “sinal” quando um evento ocorrer para que outras partes do seu aplicativo possam responder.

django_ecommerce/carts/models.py


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)
    total = models.DecimalField(default = 0.00, max_digits=100, decimal_places = 2)
    subtotal = 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):
  #print(action)
  if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
    #print(instance.products.all())
    #print(instance.total)
    products = instance.products.all() 
    total = 0 
    for product in products: 
      total += product.price 
    if instance.subtotal != total:
      instance.subtotal = total
      instance.save()
    #print(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):
  instance.total = instance.subtotal + 10 # considere o 10 como uma taxa de entrega

pre_save.connect(pre_save_cart_receiver, sender = Cart)

Como incluímos o campo subtotal ao nosso carrinho, faça as migrações:


python manage.py makemigrations
python manage.py migrate

Campo subtotal

O campo subtotal é para, por exemplo, ser possível mostrar o total da soma dos produtos e deixar o campo total para a soma geral, ou seja, o subtotal + taxas + frete + .

Quando a gente clicar em salvar, a pre_save_cart_receiver() vai ser chamada.

Você pode notar que se você selecionar os produtos e salvar, o total não muda, a função receiver tá sendo executada, mas o resultado não tá refletindo no campo total.

É aí que entra o signals.

O fato do produto ter uma relação muitos para muitos, a gente vai usar o signals m2m_changed, para quando selecionarmos os produtos e salvar, o resultado reflita no campo total.

Voltando a Views do Cart como era antes, mas mais enxutinha,  só que com as duas variáveis cart_obj e new_obj recebendo o retorno de new_or_get().

django_ecommerce/carts/views.py


from django.shortcuts import render
from .models import Cart

def cart_home(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    return render(request, "carts/home.html", {})

Abra a página de admin para testar.

Voltar para página principal do blog

Todas as aulas desse curso

Aula 42               Aula 44

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

É isso, ficamos por aqui \o/ e até a próxima 😉

 

About The Author
-

1 comentário

  • Marco
    Reply

    Olá Toti, primeiramente quero agradecer o conteúdo sensacional, meus parabéns e pedir para rever os códigos (if request.user.is_authenticate and cart_obj.user is None:) e (if user.is_authenticate), pois ambos são (is_authenticated)

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>