Aula 62 – Loja Online – Associando o endereço ao pedido
Aula 62 – Loja Online – Associando o endereço ao pedido
Voltar para página principal do blog
Todas as aulas desse curso
Aula 61 Aula 63
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
Quer aprender python3 de graça e com certificado? Acesse então:
https://workover.com.br/python-codigo-fluente
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 62 – Loja Online – Associando o endereço ao pedido
Vamos agora associar o Address ao Order.
Abra o arquivo models.py do order e vamos importar o Address acrescentar os campos shipping_address e billing_address.
eCommerce/src/orders/models.py
import math
from django.db import models
from django.db.models.signals import pre_save, post_save
from addresses.models import Address
from billing.models import BillingProfile
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 OrderManager(models.Manager):
def new_or_get(self, billing_profile, cart_obj):
created = False
qs = self.get_queryset().filter(
billing_profile = billing_profile,
cart = cart_obj,
active = True)
if qs.count() == 1:
obj = qs.first()
else:
obj = self.model.objects.create(
billing_profile = billing_profile,
cart=cart_obj)
created = True
return obj, created
class Order(models.Model):
billing_profile = models.ForeignKey(BillingProfile, on_delete=models.CASCADE, null = True, blank = True)
order_id = models.CharField(max_length = 120, blank = True)
# billing_profile = ?
shipping_address = models.ForeignKey(Address, related_name="shipping_address", on_delete=models.CASCADE, null=True, blank=True)
billing_address = models.ForeignKey(Address, related_name="billing_address", on_delete=models.CASCADE, null=True, blank=True)
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)
active = models.BooleanField(default=True)
def __str__(self):
return self.order_id
objects = OrderManager()
def update_total(self):
cart_total = self.cart.total
shipping_total = self.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)
# return all orders with this Cart instance, excluding those
# that have the same billing profile instance
qs = Order.objects.filter(cart = instance.cart).exclude(billing_profile = instance.billing_profile)
print("QuerySet: ", qs)
if qs.exists():
qs.update = False
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)
Perceba que utilizamos related_name nos campos shipping_address e no billing_address.
Como estamos associando dois campos diferentes ao modelo Address, isso pode confundir o Django e ocorrer alguns problemas.
Para evitar isso, utilizamos um nome alternativo para este campo usando o related_name, e aí então o Django pode usar para fazer essa associação sem que haja problemas pelo fato de termos duas associações com nomes iguais.
Migrações
Vamos fazer as migrações para repercutir as mudanças no modelo do Orders no banco de dados.
python manage.py makemigrations
Agora o migrate.
python manage.py migrate
Vamos obter esses endereços no views.py do carts.
django_ecommerce/e_commerce/carts/views.py
from django.shortcuts import render, redirect
from accounts.forms import LoginForm, GuestForm
from accounts.models import GuestEmail
from addresses.forms import AddressForm
from addresses.models import Address
from billing.models import BillingProfile
from orders.models import Order
from products.models import Product
from .models import Cart
def cart_home(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
return render(request, "carts/home.html", {"cart": cart_obj})
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id is not None:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("Mostrar mensagem ao usuário, esse produto acabou!")
return redirect("cart:home")
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
else:
cart_obj.products.add(product_obj) # cart_obj.products.add(product_id)
request.session['cart_items'] = cart_obj.products.count()
# return redirect(product_obj.get_absolute_url())
return redirect("cart:home")
def checkout_home(request):
#aqui a gente pega o carrinho
cart_obj, cart_created = Cart.objects.new_or_get(request)
order_obj = None
#se o carrinho acabou de ser criado, ele tá zerado
#ou se o carrinho já existir mas não tiver nada dentro
if cart_created or cart_obj.products.count() == 0:
return redirect("cart:home")
login_form = LoginForm()
guest_form = GuestForm()
address_form = AddressForm()
billing_address_id = request.session.get("billing_address_id", None)
shipping_address_id = request.session.get("shipping_address_id", None)
billing_profile, billing_profile_created = BillingProfile.objects.new_or_get(request)
if billing_profile is not None:
order_obj, order_obj_created = Order.objects.new_or_get(billing_profile, cart_obj)
if shipping_address_id:
order_obj.shipping_address = Address.objects.get(id = shipping_address_id)
del request.session["shipping_address_id"]
if billing_address_id:
order_obj.billing_address = Address.objects.get(id = billing_address_id)
del request.session["billing_address_id"]
if billing_address_id or shipping_address_id:
order_obj.save()
context = {
"object": order_obj,
"billing_profile": billing_profile,
"login_form": login_form,
"guest_form": guest_form,
"address_form": address_form,
}
return render(request, "carts/checkout.html", context)
Agora vamos colocar o blling_address e o shipping_address na sessão em si.
para fazer isso, abra o views.py do address e coloque
django_ecommerce/e_commerce/addresses/views.py
from django.shortcuts import render, redirect
from django.utils.http import url_has_allowed_host_and_scheme
from billing.models import BillingProfile
from .forms import AddressForm
def checkout_address_create_view(request):
form = AddressForm(request.POST or None)
context = {
"form": form
}
next_ = request.GET.get('next')
next_post = request.POST.get('next')
redirect_path = next_ or next_post or None
if form.is_valid():
print(request.POST)
instance = form.save(commit=False)
billing_profile, billing_profile_created = BillingProfile.objects.new_or_get(request)
if billing_profile is not None:
address_type = request.POST.get('address_type', 'shipping')
instance.billing_profile = billing_profile
instance.address_type = address_type
instance.save()
request.session[address_type + "_address_id"] = instance.id
print(address_type + "_address_id")
else:
print("Error here")
return redirect("cart:checkout")
if url_has_allowed_host_and_scheme(redirect_path, request.get_host()):
return redirect(redirect_path)
else:
return redirect("cart:checkout")
return redirect("cart:checkout")
Vamos testar!
Com servidor rodando, acesse a página de checkout, se tudo ocorrer bem, o form do Shipping Address deve ser mostrado.
Depois de preencher e clicar no botão submit, o form do Billing Address deve ser mostrado.
Depois de clicar em submit, a página de finalização do checkout deve ser mostrada.
Acesse a página de admin e clique em orders, veja que a última order que você acabou de criar, tem os dois endereços, o Shipping Address e o Billing Address.