Aula 12 - Ecommerce - Django - Custom Model Managers
Loja Virtual - Ecommerce - Django - Custom Model Managers
Custom Model Managers ou Gestores de Modelos Personalizados
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
Na próxima aula veremos como personalizar querysets (Featured Custom QuerySets).
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:
Esse outro link é da one.com:
Obrigado, até a próxima e bons estudos. ;)