Aula 70 – Loja Online – JQuery – Produtos Assíncrono

Aula 70 – Loja Online – JQuery – Produtos Assíncrono

Loja Online - Django - JQuery

Loja Online – Django – JQuery

Voltar para página principal do blog

Todas as aulas desse curso

Aula 69                       Aula 71

Dêem um joinha 👍 na página do Código Fluente no
Facebook.

Sigam o Código Fluente no Instagram e no TikTok.

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

PIX para doações

PIX Nubank

PIX Nubank

Se quiser copiar o código do PIX:

00020126580014BR.GOV.BCB.PIX013643c5f950-535b-4658-b91f-1f1d135fe4105204000053039865802BR5925Antonio Cavalcante de Pau6009SAO PAULO61080540900062070503***6304946B


Automatize tarefas do dia a dia com python:

Curso Python Bot

Curso Python Bot

Aula 70 – Loja Online – JQuery – Produtos Assíncrono

Aplicações web modernas

Em aplicações web modernas, você já deve ter se deparado com animações de loading, quando você clica em algo que a aplicação demora um pouquinho para dá uma resposta de volta.

Isso acontece quando a aplicação precisa, por exemplo, ir ao banco de dados para pegar algum dado, e trazer de volta para o frontend, ou vice-versa.

Carregamento Síncrono vs. Assíncrono

O carregamento síncrono é o que fizemos até agora, nós fazemos uma tarefa e esperamos até que a tarefa termine de ser executada para fazer uma próxima tarefa.

Um exemplo disso é quando adicionamos um produto ao carrinho.

Um carregamento assíncrono não precisa que você recarregue a página, assim como não precisa esperar que uma tarefa termine para poder fazer a próxima coisa.

Não é preciso travar a usabilidade do app para esperar que o servidor de banco de dados ou qualquer outra coisa, termine alguma tarefa.

Um exemplo disso é um botão de like do facebook, ou um botão de inscrição do youtube, as coisas acontecem em segundo plano, sem que paralise a aplicação para esperar que essa tarefa seja concluída não afetando a usabilidade do app.

Projeto Ecommerce

A forma como o ecommerce que estamos construindo executa as tarefas até agora é totalmente síncrona.

Tudo que fazemos, como por exemplo, visualizar os detalhes de um produto, ou adicionar um produto ao carrinho, é executado em sequencia, uma coisa de cada vez, e a cada ação em que repercute em mudança na tela do browser, o app faz o reload da página toda e só depois que a página é totalmente carregada, que o usuário pode fazer outra coisa.

Se você clica no botão de remover do carrinho, perceba que a página é recarregada totalmente, quando o melhor seria que só a parte que realmente mudou na página fosse recarregada.

Implementando Jquery no projeto

Vamos começar pelo app Products.

Primeira coisa, fazer o Ajax funcionar no projeto.

No e_commerce/templates/base/js.html, vamos trocar o jquery-3.3.1.slim.min.js por jquery-3.3.1.min.js, porque no slim não tem o Ajax.

E também tirar o integrity=”sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo” crossorigin=”anonymous”.

Então ele vai ficar assim:

e_commerce/templates/base/js.html


{% load static %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

É uma boa ideia em JQuery, ter uma classe para identificar o form de maneira única.

e_commerce/products/templates/products/snippets/update-cart.html 


<form class='form-product-ajax' method='POST' action='{% url "cart:update" %}' class="form"> {% csrf_token %}
 <input type='hidden' name='product_id' value='{{ product.id }}' />
 {% if in_cart %}
  <button type='submit' class='btn btn-link btn-sm' style="padding:0px;cursor: pointer;">
   Excluir
  </button>
 {% else %}
  {% if product in cart.products.all %}
   No carrinho <button type='submit' class='btn btn-link'>Excluir</button>
  {% else %}
   <button type='submit' class='btn btn-success'>Adicionar</button>
  {% endif %}
 {% endif %}
</form>

Agora, no base.html, vamos inserir o nosso script JQuery.

Note que o event.preventDefault() não vai deixar o form ser enviado.

e_commerce/templates/base.html


{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
          event.preventDefault();
          console.log("O formulário não foi enviado!")
        })
      })
    </script>
  </body>
</html>

Se você clicar no botão Adicionar, não vai acontecer nada por causa do event.preventDefault().

Faça o teste, aperte o F12 do teclado e escolha a aba console, em seguida clique no botão Adicionar, na página do produto e veja o print do console.log() dentro do console.

Vamos pegar agora os dados do form, o método e a ação e dá um console.log() neles.

e_commerce/templates/base.html


{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
          event.preventDefault();
          console.log("O formulário não foi enviado!");
          // o this pega os dados relacionados a esse form
          const thisForm = $(this);
          const actionEndpoint = "";
          const httpMethod = "";
          const formData = "";
          console.log("Ação:", thisForm.attr("action"));
          console.log("Método:", thisForm.attr("method"));
        })
      })
    </script>
  </body>
</html>

Faça o teste adicionando o produto ao carrinho e veja o resultado dos console.log().

Agora vamos fazer a chamada Ajax.

e_commerce/templates/base.html


{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
          event.preventDefault();
          console.log("O formulário não foi enviado!");
          // o this pega os dados relacionados a esse form
          const thisForm = $(this);
          const actionEndpoint = thisForm.attr("action");
          const httpMethod = thisForm.attr("method");
          const formData = thisForm.serialize();
          $.ajax({
            url: actionEndpoint,
            method: httpMethod,
            data: formData,
            success: function(data){
              console.log("Sucesso")
              console.log(data)
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        })
      })
    </script>
  </body>
</html>

Acione o Preserve log nas configurações do console do browser.

Veja que agora quando clicamos em Adicionar, o app manda de volta o resultado do console.log() de sucesso, e também um documento html.

Isso acontece porque a função cart_update() do views do cart, retorna um html como resposta.

Vamos fazer um teste, coloque o código em azul clique em Adicionar e veja o resultado do print() no console do servidor.

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 request.is_ajax():
        print("Ajax request")
    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)
    address_qs = None
    if billing_profile is not None:
        if request.user.is_authenticated:
            address_qs = Address.objects.filter(billing_profile=billing_profile)
        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()
    if request.method == "POST":
        #verifica se o pedido foi feito
        is_done = order_obj.check_done()
        if is_done:
            order_obj.mark_paid()
            request.session['cart_items'] = 0
            del request.session['cart_id']
            return redirect("cart:success")
    
    context = {
        "object": order_obj,
        "billing_profile": billing_profile,
        "login_form": login_form,
        "guest_form": guest_form,
        "address_form": address_form,
        "address_qs": address_qs,
    }
    return render(request, "carts/checkout.html", context)

def checkout_done_view(request):
    return render(request, "carts/checkout-done.html", {})

Na próxima aula vamos ver como o Django lida com o Ajax no backend.

É isso, ficamos por aqui e até a próxima. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 69                       Aula 71

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>