from random import choicecategories = ('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 categoriasCategory.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 produtosProduct.objects.bulk_update(products, ['category'])
Vamos iterar por todos os produtos. E imprimir o nome da categoria.
from django.db import connectionproducts = 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 connectionproducts = Product.objects.select_related('category').all()for product in products:print(product.category)print(len(connection.queries))# 1
O objetivo do select_related é realizar uma única query que une todos os models relacionados. Ele faz isso através de um JOIN na instrução SQL, então realiza o cache do atributo para que possa acessá-lo sem realizar uma nova consulta. Só que ele não funciona para ManyToMany, e nem para Relacionamento Reverso.
Relacionamento Reverso
Por padrão o Django adiciona um relacionamento reverso quando sua tabela é referenciada por uma chave estrangeira.
Se não passar o parâmetro related_name, irá seguir o padrão <nome_tabela>_set.
A partir do Livro, vamos acessar todos os autores dele.
from django.db import connectionbooks = 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 connectionauthors = 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.
Retorne todas as categorias, e a partir de cada categoria retorne todos os produtos desta categoria.
from django.db import connectioncategories = 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 crescenteProduct.objects.all().order_by('-title')# ordem decrescenteProduct.objects.all().order_by('created')# mais antigo primeiroProduct.objects.all().order_by('-created')# mais recente primeiro
Retornando uma lista de registros
Para retornar uma lista de registros usamos o flat = True.