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.
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)
Bom dia!
Qual é o valor para obter o certificado do curso?
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 🙂
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?
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/