Um QuerySet é uma coleção de dados de um banco de dados.
Um QuerySet é construído como uma lista de objetos.
Os QuerySets facilitam a obtenção dos dados de que você realmente precisa, permitindo que você filtre e ordene os dados.
Neste tutorial consultaremos dados da tabela Livros.
id | primeiro_nome | ultimo_nome |
---|---|---|
1 | O Dia de Amanhã | Jorge Dias |
2 | O Sol Amarelo | Maria Amélia |
3 | A Viagem | Joana Martins |
4 | Carros em Fuga | José Silva |
5 | O Baralho do Mágico | Ana Torres |
As views são funções para conter código mesclando templates e dados para serem retornados como resposta-http aos clientes.
A função view_comum(request, meus_livros) tem as instruções básicas comums às views, onde a alteração ocorre no conjunto de itens retornados na consulta de dados.
São dois argumentos da função:
São três instruções no bloco da função:
São importados dois módulos de objetos utilizados no bloco da função:
from django.http import HttpResponse
from django.template import loader
#
def view_comum(request, meus_livros):
template = loader.get_template('template.html')
context = {'meus_livros': meus_livros,}
return HttpResponse(template.render(context,request))
Em views.py, temos views para teste chamadas teste_01, teste_02, teste_03 e assim por diante, para testarem diferentes consultas.
No exemplo abaixo utilizamos o método .all() para obter todos os registros e campos do modelo Livros:
livros/views.py:import Livros
def teste_01(request):
meus_livros = Livros.objects.all()
return view_comum(meus_livros)
O objeto é colocado em uma variável chamada meus_livros, e é enviado para o modelo por meio do contextobjeto como meus_livros, e se parece com isso:
<QuerySet [
<Livros: Livros object (1)>,
<Livros: Livros object (2)>,
<Livros: Livros object (3)>,
<Livros: Livros object (4)>,
<Livros: Livros object (5)>
]>
Como você pode ver, nosso modelo Livros contém 5 registros e são listados dentro do QuerySet como 5 objetos.
No template você pode usar o meus_livros objeto para gerar conteúdo:
template.html:
<table> border='1'>
<tr>>
<th>ID</th>
<th>Firstname</th>
<th>Lastname</th>
</tr>>
{% for x in meus_livros %}
<tr>>
<td>{{ x.id }}</td>
<td>{{ x.titulo_autor }}</td>
<td>{{ x.lastname }}</td>
</tr>>
{% endfor %}
</table>>
Existem diferentes métodos para obter dados de um modelo em um QuerySet.
O método values() permite retornar cada objeto como um dicionário Python, com os nomes e valores como pares chave/valor:
livros/views.py:from .models import Livros
def teste_02(request):
meus_livros = Livros.objects.all().values()
return view_comum(request,meus_livros)
O método values_list() retorna as colunas especificadas.
View: livros/views.py:
from .models import Livros
def teste_03(request):
meus_livros = Livros.objects.values_list('titulo_autor')
return view_comum(request,meus_livros)
Você pode filtrar a pesquisa para retornar apenas linhas/registros específicos, usando o método filter().
View: livros/views.py:
import Livros
def teste_04(request):
meus_livros = Livros.objects.filter(titulo_autor='Emil').values()
return view_comum(meus_livros)
O método filter() é usado para filtrar sua pesquisa e permite retornar apenas as linhas que correspondem ao termo de pesquisa.
Como aprendemos no capítulo anterior, podemos filtrar os nomes dos campos como este:
Exemplo
Retorna apenas os registros onde o primeiro nome é 'Emil':
meus_livros = Livros.objects.filter(titulo_autor='Emil').values()
Em SQL, a instrução acima seria escrita assim:
SELECT * FROM livros WHERE titulo_autor = 'Emil';
O método filter() recebe os argumentos como **kwargs (argumentos de palavras-chave), então você pode filtrar em mais de um campo separando-os por vírgula.
Exemplo: retornar os registros onde o sobrenome é "Refsnes" e o id é 2.
meus_livros = Livros.objects.filter(lastname='Refsnes', id=2).values()
Em SQL, a instrução acima seria escrita assim:
SELECT * FROM livros WHERE lastname = 'Refsnes' AND id = 2;
Retornar registros onde o nome é Emil ou o nome é Tobias (significando: retornar registros que correspondam a qualquer consulta, não necessariamente a ambos) não é tão fácil quanto o exemplo AND acima.
Podemos usar vários métodos filter(), separados por uma barra vertical |. Os resultados serão mesclados em um modelo.
Exemplo: retornar registros onde o primeiro nome é "Emil" ou Tobias":
meus_livros = Livros.objects.filter(titulo_autor='Emil').values() | Livros.objects.filter(titulo_autor='Tobias').values()
Outro método comum é importar e usar expressões Q:
Exemplo: retorna registros onde o primeiro nome é "Emil" ou Tobias".
from .models import Livros
from django.db.models import Q
#
def teste_05(request):
meus_livros = Livros.objects.filter(Q(titulo_autor='Emil') | Q(titulo_autor='Tobias')).values()
return view_comum(meus_livros)
Em SQL, a instrução acima seria escrita como:
SELECT * FROM livros WHERE titulo_autor = 'Emil' OR titulo_autor = 'Tobias';
O Django tem sua própria maneira de especificar instruções SQL e cláusulas WHERE.
Para especificar onde cláusulas no Django, use "pesquisas de campo".
Pesquisas de campo são palavras-chave que representam palavras-chave SQL específicas.
Exemplo:
.filter(firstname__startswith='L');
É o mesmo que a instrução SQL:
WHERE titulo_autor LIKE 'L%'
A instrução acima retornará registros onde titulo_autor começa com 'L'.
Todas as palavras-chave de pesquisa de campo devem ser especificadas com o nome do campo, seguido por dois (!) caracteres de sublinhado e a palavra-chave.
Em nosso modelo de Livros, a declaração seria escrita assim:
Exemplo: Retorne os registros onde o nome começa com a letra 'L'.
meus_livros = Livros.objects.filter(firstname__startswith='L').values()
Uma lista de todas as palavras-chave de pesquisa de campo:
Palavra-chave | Descrição |
---|---|
contains | Contém a frase |
icontains | O mesmo que contains, mas não diferencia maiúsculas de minúsculas |
date | Corresponde a uma data |
day | Corresponde a uma data (dia do mês, 1-31) (para datas) |
endswith | Termina com |
iendswith | O mesmo que endswidth, mas não diferencia maiúsculas de minúsculas |
exact | Uma correspondência exata |
iexact | O mesmo que exact, mas não diferencia maiúsculas de minúsculas |
in | Corresponde a um dos valores |
isnull | Corresponde a valores NULL |
gt | Maior que |
gte | Maior ou igual a |
hour | Corresponde a uma hora (para datetimes) |
lt | Menor que |
lte | Menor ou igual a |
minute | Corresponde a um minuto (para datas e horários) |
month | Corresponde a um mês (para datas) |
quarter | Corresponde a um trimestre do ano (1-4) (para datas) |
range | Correspondência entre |
regex | Corresponde a uma expressão regular |
iregex | O mesmo que regex, mas não diferencia maiúsculas de minúsculas |
second | Corresponde a um segundo (para datetimes) |
startswith | Começa com |
isstartswith | Igual a startswith, mas não diferencia maiúsculas de minúsculas |
time | Corresponde a uma hora (para datetimes) |
week | Corresponde a um número de semana (1-53) (para datas) |
week_day | Corresponde a um dia da semana (1-7) 1 é domingo |
iso_week_day | Corresponde a um dia da semana ISO 8601 (1-7) 1 é segunda-feira |
year | Corresponde a um ano (para datas) |
iso_year | Corresponde a um ano ISO 8601 (para datas) |
Para classificar QuerySets, o Django usa o método order_by().
Exemplo: Ordene o resultado em ordem alfabética por nome.
meus_livros = Livros.objects.all().order_by('titulo_autor').values()
Em SQL, a instrução acima seria escrita assim:
SELECT * FROM livros ORDER BY titulo_autor;
Por padrão, o resultado é classificado em ordem crescente (o valor mais baixo primeiro), para alterar a direção para decrescente (o valor mais alto primeiro), use o sinal de menos (NOT), -na frente do nome do campo:
Exemplo: Ordene o primeiro nome do resultado de forma decrescente.
meus_livros = Livros.objects.all().order_by('-titulo_autor').values()
Em SQL, a instrução acima seria escrita assim:
SELECT * FROM livros ORDER BY titulo_autor DESC;
Para ordenar por mais de um campo, separe os nomes dos campos com uma vírgula no método order_by().
Exemplo: ordene o resultado primeiro por sobrenome crescente e depois decrescente em id.
meus_livros = Livros.objects.all().order_by('lastname', '-id').values()
Em SQL, a instrução acima seria escrita assim:
SELECT * FROM livros ORDER BY lastname ASC, id DESC;