Aula 11 – Loja Online – Ecommerce – Django – Consultas ao Banco de Dados

Aula 11 – Loja Online – Ecommerce – Django – Consultas ao Banco de Dados

Loja Virtual – Ecommerce – Django – Consultando o Banco de Dados via shell

Lookups

Na aula passada construímos a parte referente a upload de imagens dos produtos.

Vimos que o django na hora do upload da imagem, cria um sufixo aleatório para dá uma identidade única as imagens e evitar que imagem que tenham o mesmo nome por coincidência, seja subscrita no seu CDN na hora de fazer upload de novas imagens.

Ele também elimina os espaços em branco entre palavras, substituindo por underscore, para evitar problemas, já que espaço em branco em nomes de pastas e arquivos sempre podem ocasionar contratempos inesperados.

Consultando o Banco de Dados via shell

Consultando o Banco de Dados via shell

Voltar para página principal do blog

Todas as aulas desse curso

Aula 10                Aula 12

Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/lookups

Curta a página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/

Vou deixar meu link de referidos na digitalocean pra vocês.

Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:

Digital Ocean

Esse outro link é da one.com:

One.com

Lookups é a forma como são especificadas as condições na cláusula WHERE de um SQL.

Condições da pesquisa

As condições são especificadas como argumentos de palavra-chave para os métodos de pesquisa (QuerySet) como filter(), exclude() e get().

Contains e o icontains verifica se a string fornecida está contida no campo valor no banco de dados. O contains é traduzido para LIKE e o icontains para ILIKE em SQL.

O contains diferencia maiúsculas de minúsculas (case-sensitive) o icontains não (case-insensitive).

Vamos abrir o shell do django.

python manage.py shell

O prompt muda para um prompt python ( >>> )

Faça o seguinte import.

from products.models import Product

Vamos dá uma olhada no queryset um pouco mais profundamente.

queryset = Product.objects.all()
queryset

Saída:

<Queryset [<Product: Camiseta>, <Product: Tênis>]>

Semelhante ao comando sql:

SELECT * FROM products_product;

A gente pode também filtrar.

qs = Product.objects.filter(title__contains = "seta")
qs

Saída:

<Queryset [<Product: Camiseta>]>

Semelhante ao comando sql:

SELECT * FROM products_product;
WHERE title LIKE '%seta%';

Vamos buscar algo que não tenha.

qs = Product.objects.filter(title__contains = "carro")
qs

Saída:

<Queryset []>

qs = Product.objects.filter(description__icontains = "edição limitada")
qs

Saída:

<Queryset [<Product: Camiseta>]>

qs = Product.objects.filter(description__icontains = "tecnologia inovadora")

Saída:

<Queryset [<Product: Tênis>]>

qs = Product.objects.filter(title__icontains = "Cami", description__iexact = 'Abc')

Saída:

<Queryset []>

qs = Product.objects.filter(title__icontains = "Cami", description__iexact = 'Essa camiseta é uma edição limitada, é exclusiva e apenas algumas unidades estão disponíveis.')

Saída:

<Queryset [<Product: Camiseta>]>


qs = Product.objects.filter(pk = 1)
qs

Saída:

<Queryset [<Product: Camiseta>]>


qs = Product.objects.filter(id = 1)
qs

Saída:

<Queryset [<Product: Camiseta>]>

Tanto faz usar id ou pk.

Se tentar acessar com o get um id que não existe

qs = Product.objects.get(pk = 4)

Será mostrada uma mensagem de erro:

Traceback (most recent call last):
File “<console>”, line 1, in <module>
File “/home/toticavalcanti/django_ecommerce/lib/python3.6/site-packages/django/db/models/manager.py”, line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File “/home/toticavalcanti/django_ecommerce/lib/python3.6/site-packages/django/db/models/query.py”, line 399, in get
self.model._meta.object_name
products.models.Product.DoesNotExist: Product matching query does not exist.

Isso é considerado um erro de servidor.

É por isso que temos o get_object_or_404 na function product_detail_view() no src/products/views.py.

Vamos modificar o src/products/views.py para lidar com esse erro de uma forma um pouco melhor:


from django.http import Http404
from django.views.generic import ListView, DetailView
from django.shortcuts import render, get_object_or_404

from .models import Product

#Class Based View
class ProductListView(ListView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/list.html"
    
    #def get_context_data(self, *args, **kwargs):
        #context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        #print(context)
        #return context

#Function Based View
def product_list_view(request):
    queryset = Product.objects.all()
    context = {
        'object_list': queryset
    }
    return render(request, "products/list.html", context)

#Class Based View
class ProductDetailView(DetailView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/detail.html"
    
    def get_context_data(self):
        context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        print(context)
        return context

#Function Based View
def product_detail_view(request, pk = None, *args, **kwargs):
    #instance = Product.objects.get(pk = pk) #get the object id
    #instance = get_object_or_404(Product, pk = pk)
    try:
        instance = Product.objects.get(id = pk)
    except Product.DoesNotExist:
        print("Nenhum produto encontrado aqui!")
        raise Http404("Esse produto não existe!")

    context = {
        'object': instance
    }
    return render(request, "products/detail.html", context)

Acesse um produto que não exista e veja o print no console do servidor e o raise http404 no browser.

Vamos modificar de novo src/products/views.py para lidar com esse erro de uma forma melhor ainda, menos verbosa, vamos deletar tudo que fizemos no passo anterior com o try except e substituir pelo que tá em laranja:


from django.http import Http404
from django.views.generic import ListView, DetailView
from django.shortcuts import render, get_object_or_404

from .models import Product

#Class Based View
class ProductListView(ListView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/list.html"
    
    #def get_context_data(self):
        #context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        #print(context)
        #return context

#Function Based View
def product_list_view(request):
    queryset = Product.objects.all()
    context = {
        'object_list': queryset
    }
    return render(request, "products/list.html", context)

#Class Based View
class ProductDetailView(DetailView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/detail.html"
    
    def get_context_data(self):
        context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        print(context)
        return context

#Function Based View
def product_detail_view(request, pk = None, *args, **kwargs):
    #instance = Product.objects.get(pk = pk) #get the object id
    #instance = get_object_or_404(Product, pk = pk)
    qs = Product.objects.filter(id = pk)
    if qs.exists():
        instance = qs.first()
    else:
        raise Http404("Esse produto não existe!")

    context = {
        'object': instance
    }
    return render(request, "products/detail.html", context)

qs.exists() vs qs.count()

O queryset tem um método mais eficiente para o banco de dados do que o qs.exists(), que é o qs.count(), então vamos usar ele ao invés do qs.exists().

Vamos modificar novamente o src/products/views.py, substituindo o qs.exists() pelo qs.count() == 1:


from django.http import Http404
from django.views.generic import ListView, DetailView
from django.shortcuts import render, get_object_or_404

from .models import Product

#Class Based View
class ProductListView(ListView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/list.html"
    
    #def get_context_data(self, *args, **kwargs):
        #context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        #print(context)
        #return context

#Function Based View
def product_list_view(request):
    queryset = Product.objects.all()
    context = {
        'object_list': queryset
    }
    return render(request, "products/list.html", context)

#Class Based View
class ProductDetailView(DetailView):
    #traz todos os produtos do banco de dados sem filtrar nada 
    queryset = Product.objects.all()
    template_name = "products/detail.html"
    
    def get_context_data(self):
        context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
        print(context)
        return context

#Function Based View
def product_detail_view(request, pk = None, *args, **kwargs):
    #instance = Product.objects.get(pk = pk) #get the object id
    #instance = get_object_or_404(Product, pk = pk)
    if qs.count() == 1:
        instance = qs.first()
    else:
        raise Http404("Esse produto não existe!")

    context = {
        'object': instance
    }
    return render(request, "products/detail.html", context)

Valeu, até a próxima! 🙂

Aula 10                Aula 12

Todas as aulas desse curso

Voltar para página principal do blog

Curta a página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/

Vou deixar meu link de referidos na digitalocean pra vocês.

Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:

Digital Ocean

Esse é o link da one.com:

One.com

Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/lookups

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

4 Comentários

  • Gracielle Antunes de Araújo
    Reply

    Bom dia!
    Qual é o valor para obter o certificado do curso?

    • toticavalcanti
      Reply

      E aí Gracielle, blz?
      O código fluente é um curso informal, por isso, não tem certificado, eu apenas compartilho conhecimento a medida do que vou estudando.
      Acredito que principalmente na área de tecnologia, o mais importante é você fazer, colocar a mão na massa.
      Claro que uma curadoria ajuda bastante, então por isso, fazer um curso técnico, ou de graduação, ou pós é muito bom, mas, na verdade aprendemos fazendo, errando, pedindo ajuda, e estudando muito.
      As certificações ainda são valorizadas, porem, empresas mais alinhadas com o nosso tempo valorizam cada vez mais o que somos capaz de produzir e impactar positivamente o mundo a nossa volta.
      As ideias alinhadas as necessidades humanas são o mais importante, como executar, a gente aprende se dedicando, com certificação ou não.
      \o/ Gracielle 🙂

  • Yuri Martins
    Reply

    Fala toti, tudo bom? Seus videos são muito bem feitos e seu blog muito bem organizado, parabéns pelo trabalho. Deixa eu perguntar também… Na questão de dar um Product.objects.filter() em class based view, como ficaria?

    • toticavalcanti
      Reply

      Opa Yuri, blz?
      Na classe-based view, a parte Product.objects.filter() seria definida no atributo queryset da classe.
      O atributo queryset define a consulta para obter os objetos.
      queryset = Product.objects.all()
      O Product.objects.all() retorna todos os objetos da classe Product.
      Você pode ajustar o queryset conforme necessário para filtrar os objetos de acordo com suas necessidades.
      Por exemplo, o equivalente a:
      qs = Product.objects.filter(id=pk)
      Ficaria assim em uma class based view:
      queryset = super().get_queryset()
      queryset = queryset.filter(id=self.kwargs['pk'])

      A variável queryset representa o queryset original que é retornado pelo método get_queryset().

      Ao acessar o valor pk da URL através de self.kwargs[‘pk’], você pode filtrar o queryset com base no valor do id fornecido na URL. Portanto, a linha queryset = queryset.filter(id=self.kwargs[‘pk’]) filtra o queryset original para incluir apenas o objeto Product com o id correspondente.

      Lembre-se de que o método get_queryset() é chamado internamente pela classe-based view para obter o queryset a ser utilizado. Portanto, ao substituir esse método e ajustar o queryset, você está filtrando os objetos de acordo com o id especificado na URL.

      Vale Yuri
      \o/

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>