from random import choice
categories = (
'AcessĂłrios de Moda',
'Artigos de Ginástica e Esportes',
'Artigos de Praia e Piscina',
'Artigos para Presente',
'Calçado Feminino',
'Calçado Masculino',
'Cama, Mesa e Banho',
'Roupa Feminina',
'Roupa Infantil',
'Roupa Masculina',
)
# Deleta as categorias
Category.objects.all().delete()
# Cria as categorias com list comprehension
[Category.objects.create(title=title) for title in categories]
categories = Category.objects.all()
products = Product.objects.all()
for product in products:
# Escolhe uma catetoria
category = choice(categories)
product.category = category
# Aplica a categoria em todos os produtos
Product.objects.bulk_update(products, ['category'])
Vamos iterar por todos os produtos. E imprimir o nome da categoria.
from django.db import connection
products = Product.objects.all()
for product in products:
print(product.category)
print(len(connection.queries))
# 500
Note que foram feitas 500 consultas no banco de dados. E isso torna a nossa query lenta.
select_related
Agora faça
from django.db import connection
products = Product.objects.select_related('category').all()
for product in products:
print(product.category)
print(len(connection.queries))
# 1
Se não passar o parâmetro related_name, irá seguir o padrão <nome_tabela>_set.
class Product(models.Model):
...
category = models.ForeignKey(
Category,
...
related_name='products',
)
categories = Category.objects.all()
for category in categories:
print(category.products.all())
len(connection.queries)
# 12
Significa que a partir da categoria eu consigo acessar todos os produtos.
prefetch_related
categories = Category.objects.prefetch_related('products').all()
for category in categories:
print(category.products.all())
len(connection.queries)
# 2
Exemplo com ManyToMany
Considere o bookstore/models.py
class Author(models.Model):
first_name = models.CharField('nome', max_length=100)
last_name = models.CharField('sobrenome', max_length=255, null=True, blank=True) # noqa E501
class Book(models.Model):
title = models.CharField('tĂtulo', max_length=255)
authors = models.ManyToManyField(
Author,
verbose_name='autores',
blank=True
)
...
A partir do Livro, vamos acessar todos os autores dele.
from django.db import connection
books = Book.objects.prefetch_related('authors')
for book in books:
print(book.authors.all())
len(connection.queries)
# 2
A partir do Autor, vamos acessar todos os livros dele.
from django.db import connection
authors = Author.objects.prefetch_related('book_set')
for author in authors:
print(author.book_set.all())
len(connection.queries)
# 2
Filtro Direto
Liste os produtos cuja categoria seja Roupa Masculina. E retorne o tĂtulo da categoria e o tĂtulo do produto.
from django.db import connection
category = Category.objects.get(title='Roupa Masculina')
# Bad
# products = Product.objects.filter(category=category)
# Good
products = Product.objects.select_related('category').filter(category=category)
for product in products:
print(product.category.title, product.title)
print(len(connection.queries))
# Ou
products = Product.objects.select_related('category').filter(category__title='Roupa Masculina')
Filtro Reverso
Retorne todas as categorias, e a partir de cada categoria retorne todos os produtos desta categoria.
from django.db import connection
categories = Category.objects.prefetch_related('products').all()
for category in categories:
print(category.title, category.products.all(), '\n')
# print(category.category_set.all()) # Caso vocĂŞ nĂŁo tivesse definido o related_name.
print(len(connection.queries))
Filtrando a partir de uma lista de dados
Para filtrar a partir de uma lista de dados usamos o subcomando __in.
Product.objects.all().order_by('title') # ordem crescente
Product.objects.all().order_by('-title') # ordem decrescente
Product.objects.all().order_by('created') # mais antigo primeiro
Product.objects.all().order_by('-created') # mais recente primeiro
Retornando uma lista de registros
Para retornar uma lista de registros usamos o flat = True.