Aula 12 – Ecommerce – Django – Custom Model Managers
Aula 12 – Ecommerce – Django – Custom Model Managers
Loja Virtual – Ecommerce – Django – Custom Model Managers
Custom Model Managers ou Gestores de Modelos Personalizados
Voltar para página principal do blog
Todas as aulas desse curso
Aula 11 Aula 13
Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/custom_model_managers
Vimos na aula passada, como fazer consultas ao banco pesquisando os produtos cadastrados através do queryset.
Nós fizemos isso no modelo com a ajuda do objects.
Lembra?
queryset = Product.objects.all()
Objects são considerados gerenciadores de modelos.
Um “manager” é a interface através da qual as consultas de banco de dados são fornecidas para os modelos do Django.
Padrão
Por padrão, o Django adiciona um Manager com o nome de objects para cada classe de modelo Django.
Pelo menos um Manager existe para cada modelo em uma aplicação Django.
Eles nos ajuda a fazer coisas como as querysets ou uma chamada ao próprio modelo.
Objects
O objects representa o gerente de modelo o Custom Model Managers.
Filtro
O filtro é um método do Custom Model Managers que nos permite fazer um conjunto de consultas, uma chamada get, etc.
Você pode usar um Manager personalizado em um modelo particular estendendo a classe base do Manager e instanciando seu Manager personalizado em seu modelo.
Porque usar um Custom Model Managers?
Existem dois motivos que fariam você personalizar um Manager: para adicionar métodos extra ao Manager, e/ou modificar o QuerySet inicial que o manager retorna.
Construção
Vamos fazer um Custom Model Managers um pouco mais eficaz para o nosso modelo produto.
Estratégia
Eu poderia querer obter um get object or 404, mas, talvez eu queira usar alguma forma de encontrar uma instância sem ser um get object or 404, ou um exception error.
Então, vamos lá, nosso Custom Model Manager, que vai extender o Default Model Manager.
Vá no src/products/models.py e acrescente o que tá em laranja.
from django.db import models
class ProductManager(models.Manager):
def get_by_id(self, id):
qs = self.get_queryset().filter(id = id)
if qs.count() == 1:
return qs.first()
return None
# Create your models here.
class Product(models.Model): #product_category
title = models.CharField(max_length=120)
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=20, default=100.00)
image = models.FileField(upload_to = 'products/', null = True, blank = True)
objects = ProductManager()
#python 3
def __str__(self):
return self.title
#python 2
def __unicode__(self):
return self.title
Criamos a classe ProductManager e dentro dela definimos o método get_by_id.
Dentro fizemos uma queryset para pegar o produto pelo id, ou seja, o filter irá retonar uma queryset com um só produto.
No qs.count() == 1 testamos se a queryset tá vazia ou tem um e apenas um produto, se tiver retorna o produto, senão retorna None.
O objects = ProductManager() é a chamada da nossa classe.
No src/products/views.py, modifique a FBV product_detail_view e a CBV ProductDetailView para que fique assim:
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(ProductListView, 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):
#queryset = Product.objects.all()
template_name = "products/detail.html"
def get_context_data(self, *args, **kwargs):
context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
print(context)
return context
def get_object(self, *args, **kwargs):
pk = self.kwargs.get('pk')
instance = Product.objects.get_by_id(pk)
if instance is None:
raise Http404("Esse produto não existe!")
return instance
#Function Based View
def product_detail_view(request, pk = None, *args, **kwargs):
instance = Product.objects.get_by_id(pk)
print(instance)
if instance is None:
raise Http404("Esse produto não existe!")
context = {
'object': instance
}
return render(request, "products/detail.html", context)
Na get_object da ProductDetailView (CBV), assim como na product_detail_view(FBV), pegamos o pk pelo argumento na URL através do kwargs, aí a gente chama o método do nosso Custom Model Managers que a gente criou get_by_id passando o pk.
Se a instância retornar None, a saída será um raise Http404(“Esse produto não existe!”), caso contrário, é porque o produto existe e o produto é renderizado na tela do browser.
Note que o queryset logo abaixo da declaração da ProductDetailView não é mais necessário, por isso está comentado, pode remover ele se quiser.
Faça o teste e acesse um produto existente e outyro que não exista, exemplo:
Usando a CBV:
http://127.0.0.1:8000/products/1
http://127.0.0.1:8000/products/564354
Usando a FBV:
http://127.0.0.1:8000/products-fbv/2
http://127.0.0.1:8000/products-fbv/2736