Eu quero pegar as últimas 10 instâncias de um modelo e ter este código:
Model.objects.all().order_by('-id')[:10]
É verdade que, em primeiro lugar, todas as instâncias são capturadas e depois são coletadas apenas as dez últimas? Existe algum método mais eficaz?
Respostas:
Os querysets do Django são preguiçosos. Isso significa que uma consulta atingirá o banco de dados somente quando você solicitar especificamente o resultado.
Portanto, até que você imprima ou use realmente o resultado de uma consulta, poderá filtrar ainda mais sem acesso ao banco de dados.
Como você pode ver abaixo, seu código executa apenas uma consulta sql para buscar apenas os últimos 10 itens.
fonte
Na verdade, acho que o
LIMIT 10
seria emitido para o banco de dados, para que o fatiamento não ocorresse no Python, mas no banco de dados.Veja limit-querysets para mais informações.
fonte
Parece que a solução na pergunta não funciona mais com o Django 1.7 e gera um erro: "Não é possível reordenar uma consulta depois que uma fatia foi feita"
De acordo com a documentação https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets forçando o parâmetro "step" da sintaxe de fatia do Python, avalia a consulta. Funciona assim:
Ainda me pergunto se o limite é executado em fatias SQL ou Python, toda a matriz de resultados retornada. Não é bom recuperar listas enormes para a memória do aplicativo.
fonte
Sim. Se você deseja buscar um subconjunto limitado de objetos, é possível com o código abaixo:
Exemplo:
O começo 0 é opcional, então
O código acima retorna as 10 primeiras instâncias.
fonte
Como uma adição e observação para as outras respostas úteis, vale a pena notar que, na verdade, fazer
[:10]
o fatiamento retornará os 10 primeiros elementos da lista , não os últimos 10 ...Para obter os últimos 10, você deve fazê-lo
[-10:]
(veja aqui ). Isso ajudará a evitar o usoorder_by('-id')
com o-
para reverter os elementos.fonte
Product.objects.filter(~Q(price=0))[-5:]
me causa o mesmo erro: "A indexação negativa não é suportada."