Aula 72 – Loja Online – JQuery – Contagem de Itens do Carrinho

Aula 72 – Loja Online – JQuery – Contagem de Itens do Carrinho

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 71                       Aula 73

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


Aula 72 – Loja Online – JQuery – Contagem de Itens do Carrinho

Eu atualizei o Django no meu ambiente virtual para a versão 4.0.4.

Ao rodar o código me deparei com o seguinte erro:

AttributeError: ‘WSGIRequest’ object has no attribute ‘is_ajax’ 

Pesquisando, verifiquei que desde o lançamento da versão 3.1, o método HttpRequest.is_ajax() está obsoleto, pois dependia de uma maneira específica do jQuery para significar chamadas AJAX, enquanto a forma atual usa a API JavaScript Fetch.

Dependendo do caso de uso, você pode escrever seu próprio método de detecção AJAX ou usar o novo método HttpRequest.accepts() se seu código depender do cabeçalho HTTP Accept do cliente.

O que vamos fazer é criar uma função personalizada para verificar o tipo de solicitação, no código abaixo, a parte que tá em lilás.

E mudar o if request.is_ajax() da linha 36, para if is_ajax(request).

Também vamos passar o atributo cartItemCount para a view, com “cartItemCount”: cart_obj.products.count().

O XMLHttpRequest é um objeto que fornece funcionalidade ao cliente para transferir dados entre um cliente e um servidor.

Ele fornece uma maneira fácil de recuperar dados de um URL sem ter que fazer uma atualização de página inteira.

Isso permite que uma página da Web atualize apenas uma parte do conteúdo sem interromper o que o usuário esteja fazendo.

O XMLHttpRequest é usado constantemente na programação de AJAX.

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 is_ajax(request):
    return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

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 is_ajax(request):
            print("Ajax request")
            json_data = {
                "added": added,
                "removed": not added,
                "cartItemCount": cart_obj.products.count()
            }
            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", {})

No base.html, a gente cria a constante navbarCount que atualiza o valor no browser, através do seletor navbar-cart-count indicando os itens no carrinho.

E essa variável é atualizada pelo que chega no data.cartItemCount, através do método text().

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>")
              }
                  const navbarCount = $(".navbar-cart-count")
                  navbarCount.text(data.cartItemCount)
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        })
      })
    </script>
  </body>
</html>

No navbar.html, a gente coloca um span em torno do request.session.cart_items com a classe navbar-cart-count.

e_commerce/templates/base/navbar.html


{% url 'home' as home_url %}
{% url 'contact' as contact_url %}
{% url 'products:list' as products_list_url %}
{% url 'login' as login_url %}
{% url 'logout' as logout_url %}
{% url 'register' as register_url %}
{% url 'cart:home' as cart_url %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-3">
  <div class='container'>
    <a class="navbar-brand" href="{{ home_url }}">
      <img src="https://getbootstrap.com/docs/4.0/assets/brand/bootstrap-solid.svg" width="30" height="30" class="d-inline-block align-top" alt="">
      {% if nome_da_marca %}
      {{ nome_da_marca }}
      {% else %} C&oacute;digo Fluente eCommerce
      {% endif %}
    </a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item {% if request.path == home_url %} active {% endif %}">
          <a class="nav-link" href="{{ home_url }}">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item {% if request.path == contact_url %} active {% endif %}">
          <a class="nav-link" href="{{ contact_url }}">Contato</a>
        </li>
        <li class="nav-item {% if request.path == products_list_url %} active {% endif %}">
          <a class="nav-link" href="{{ products_list_url }}">Produtos</a>
        </li>
        {% if request.user.is_authenticated %}
          <li class="nav-item {% if request.path == login_url %} active {% endif %}">
            <a class="nav-link" href="{{ logout_url }}">Logout</a>
          </li>
        {% else %}
          <li class="nav-item {% if request.path == login_url %} active {% endif %}">
            <a class="nav-link" href="{{ login_url }}?next={{request.path}}">Login</a>
          </li>
          <li class="nav-item {% if request.path == register %} active {% endif %}">
            <a class="nav-link" href="{{ register_url }}">Registrar-se</a>
          </li>
        {% endif %}
        <li class="nav-item {% if request.path == cart_url %} active {% endif %}">
          <a class="nav-link" href="{{ cart_url }}">
            <span class="navbar-cart-count">
              {{ request.session.cart_items }}
            </span>
            <i class="fa fa-shopping-cart"></i>
          </a>
        </li>
      </ul>
      {% include 'search/snippets/search-form.html' %}
    </div>
  </div><!--fim container-->
</nav>

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

Voltar para página principal do blog

Todas as aulas desse curso

Aula 71                       Aula 73

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>