Aula 71 – Loja Online – JQuery – Json Response

Aula 71 – Loja Online – JQuery – Json Response

Loja Online - Django

Loja Online – Django

Pacote Programador Fullstack

Pacote Programador Fullstack

Voltar para página principal do blog

Todas as aulas desse curso

Aula 70                       Aula 72

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 NETWORKINGLimpar o cache

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

Canais do Youtube

Toti:

Toti

Backing Track / Play-Along

Código Fluente

Putz!

PIX para doações

PIX Nubank

PIX Nubank


Automatize tarefas do dia a dia com python:

Curso Python Bot

Curso Python Bot

Aula 71 – Loja Online – JQuery – Json Response

Faça o seguinte teste.

Remova temporariamente, ou simplesmente comente o script do base.html, a parte em vermelho no código abaixo para a gente fazer um teste.

Com o código do script removido ou comentado, faça o seguinte, faça o login, vá em produtos, escolha qualquer um e adicione ao carrinho.

Aperte F12 para abrir as ferramentas de desenvolvedor no browser, e escolha a aba console.

Agora clique em Adicionar, veja que fomos para outra página.

O app está renderizando a página do carrinho, porque ele não caiu no if que teste se é uma request Ajax.

e_commerce/templates/base.html


{% load static %}
<!doctype html>
<html lang="en">
  <head>Adicionado
    <!-- 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>

Ponha o script jquery de volta no base.html, a parte em azul no código abaixo.

Faça o mesmo teste.

Dessa vez, veja que ele continua nos mandando de volta para a mesma página, mas o browser não nos redireciona para a página como no teste anterior.

O que fizemos foi transformar a request em uma request Ajax, ao invés de uma request síncrona padrão.

Isso quer dizer que a view cart_update(), retorna agora algo difeAdicionadorente de um redirect.

Volte com o código do script, o que tá em azul.

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>

Vamos então tratar a request Ajax no views.py do carts.

Será retornado uma resposta em Json(Javascript Object Notation).

Primeiro temos o import da biblioteca JsonResponse.

Depois criamos um objeto Json, que chamamos de json_data, com as chaves added e removed, e o valor é booleano.

E retornamos ele através do  JsonResponse que a gente importou.

django_ecommerce/e_commerce/carts/views.py 


from django.http import JsonResponse
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)
            added = False
        else:
            cart_obj.products.add(product_obj) # cart_obj.products.add(product_id)
            added = True
        request.session['cart_items'] = cart_obj.products.count()
        # return redirect(product_obj.get_absolute_url())
        if request.is_ajax():
            print("Ajax request")
            json_data = {
                "added": added,
                "removed": not added,
            }
            return JsonResponse(json_data)
    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", {})

Vamos acrescentar os console.log() em azul abaixo e fazer o mesmo teste, adicionar e remover um produto do carrinho e ver a saída no console do browser.

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)
              console.log("Adicionado", data.added)
              console.log("Removido", data.removed)
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        })
      })
    </script>
  </body>
</html>

Adicione um produto ao carrinho e veja o resultado do console.log() no console do browser.

Agora, com base nesse booleano retornado através do JsonResponse, iremos retornar um pedaço de html diferente do script Ajax para o update-cart.html.

Para fazer isso, usamos o seletor submit-span colocado no class do span.

django_ecommerce/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 %}
    <span class='submit-span'>
      {% 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 %}
    </span>
  {% endif %}
</form>

Então, agora vamos usar o seletor no script 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)
              console.log("Adicionado", data.added)
              console.log("Removido", data.removed)
              const submitSpan = thisForm.find(".submit-span")
              console.log(submitSpan.html())
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        })
      })
    </script>
  </body>
</html>

Vamos fazer uma condição baseada nesse booleano.

O que fazemos é substituir o html no span com o class submit-span baseado na condição.

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)
              console.log("Adicionado", data.added)
              console.log("Adicionado", data.removed)
              const submitSpan = thisForm.find(".submit-span")
              if(data.added){
                  submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
              } else{
                  submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        })
      })
    </script>
  </body>
</html>

Veja que quando adicionamos um produto ou removemos o número no carrinho não está atualizando, só se a gente fizer um refresh da página.

É isso que vamos corrigir na próxima aula.

Ficamos por aqui e até a próxima. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 70                       Aula 72

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti:

Toti

Backing Track / Play-Along

Código Fluente

Putz!

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

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>