forked from djangobrasil/django-l10n-portuguese
/
queries.txt
1048 lines (750 loc) · 41.2 KB
/
queries.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
..
.. META INFORMATION OF TRANSLATION
..
.. $TranslationStatus: Done, waiting for revision $
.. $OriginalRevision: 11332 $
.. $TranslationAuthors: Robson Mendonça $
..
.. INFO OF THIS FILE (DO NOT EDIT! UPDATED BY SUBVERSION)
..
.. $HeadURL$
.. $LastChangedRevision$
.. $LastChangedBy$
.. $LastChangedDate$
..
.. _topics-db-queries:
=================
Fazendo consultas
=================
.. currentmodule:: django.db.models
Uma vez que você tenha criado seus :ref:`data models <topics-db-models>`, o
Django automaticamente lhe dá uma API de abstração de banco de dados que permite
você criar, receber, atualizar e deletar objetos. Este documento explica como
usar esta API. Visite a :ref:`referência do model <ref-models-index>` para
detalhes completos de todas opções de model.
Por todo esse guia (e na referência), nós iremos refereir aos seguintes models,
que compreendem um aplicação de weblog:
.. _queryset-model-example:
.. code-block:: python
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author)
def __unicode__(self):
return self.headline
Criando objetos
===============
Para representar dados de uma tabela de banco de dados em objetos Python, o
Django usa um sistema intuitivo: Uma classe model representa uma tabela de banco
de dados, e uma instância dessa classe representa um dado em particular dentro
da tabela.
Para criar um objeto, instâncie-o usando argumentos nomeados para a classe
model, e então chame ``save()`` para salvá-lo no banco de dados.
You import the model class from wherever it lives on the Python path, as you
may expect. (We point this out here because previous Django versions required
funky model importing.)
Assumimos que os models estão em ``mysite/blog/models.py``, aqui tem um
exemplo::
>>> from mysite.blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
Isso executa uma consulta SQL ``INSERT`` por trás das cenas. O Django não
executa nada no banco de dados até que você, explicitamente ``save()``.
O método ``save()`` não retorna valores.
.. seealso::
O ``save()`` recebe algumas opções avançadas não descritas aqui.
Veja a documentação do ``save()`` para detalhes completos.
Para criar um objeto e salvá-lo em um passo veja o método ```create()```.
Salvando mudanças de objetos
============================
Para salvar mudanças de um objeto que já existe no banco de dados, use
``save()``.
Dado uma instância ``b5`` do ``Blog`` que já está salvo no banco de dados, este
exemplo muda seu nome e o atualiza no banco de dados::
>> b5.name = 'New name'
>> b5.save()
Isso executa uma consulta SQL ``UPDATE`` por trás das cenas. O Django não acessa
o banco de dados até que você, explicitamente, chame ``save()``.
Salvando campos ``ForeignKey`` e ``ManyToManyField``
----------------------------------------------------
Atualizar um campo ``ForeignKey`` funciona exatamente da mesma forma como salvar
um campo normal; simplesmente atribuindo um objeto do tipo certo ao campo em
questão::
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
Atualizar um ``ManyToManyField`` funciona um pouco diferente; usa o método
``add()`` sobre o campo para adicionar um dado a relação::
>> joe = Author.objects.create(name="Joe")
>> entry.authors.add(joe)
O Django se queixará se você tentar atribuir ou adicionar um objeto do tipo
errado.
Recebendo objetos
=================
Para receber objetos de seu banco de dados, você constrói uma ``QuerySet``
através do ``Manager`` de sua classe model.
Um ``QuerySet`` representa uma coleção de objetos do banco de dados. Ela poder
nenhum, um ou muitos *filtros* -- critérios que apurem a coleção baseado nos
parâmetros dados. Em termos SQL, um ``QuerySet`` equipara-se a uma consulta
``SELECT``, e um filtro é uma clausula limitadora como ``WHERE`` ou ``LIMIT``.
Você obtem um ``QuerySet`` usando o ``Manager`` de seu model. Cada model tem
pelo menos um ``Manager``, e ele é chamado ``objects`` por padrão. Acesse-o
diretamente via classe model, desta forma::
>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback:
...
AttributeError: "Manager isn't accessible via Blog instances."
.. note::
O ``Managers`` são acessível somente via classes, ao invés de instâncias,
para reforçar a separação entre operações a nível de tabela e operações a
nível de dado.
O ``Manager`` é a principal fonte de ``QuerySets`` para um model. Ele age como
uma ``QuerySet`` "raiz" que descreve todos os objetos de uma tabela de banco de
dados. Por exemplo, ``Blog.objects`` é o ``QuerySet`` inicial que contém todos
os objetos do ``Blog`` no banco de dados.
Recebendo todos os objetos
--------------------------
A forma mais simples de receber objetos da tabela é obtendo todos eles.
Para fazer isso, use o método ``all()`` de um ``Manager``::
>>> all_entries = Entry.objects.all()
O método ``all()`` retorna um `QuerySet`` de todos os objetos do banco de dados.
(Se ``Entry.objects`` é um ``QuerySet``, porquê nós fizemos um
``Entry.objects``? Isso é porque ``Entry.objects``, o ``QuerySet`` raiz, é um
caso especial que não pode ser avaliado. O método ``all()`` retorna um
``QuerySet`` que *pode* ser avaliado.)
Recebendo objetos específicos com filtros
-----------------------------------------
O ``QuerySet`` raiz fornecido pelo ``Manager`` descreve todos os objetos na
tabela de banco de dados. Geralmente, contudo, você precisará selecionar somente
um conjunto de objetos.
Para criar um subconjunto, você precisar refinar o ``QuerySet`` inicial,
adicionando confições ao filtro. As duas formas mais comuns de refinar um
``QuerySet`` são::
``filter(**kwargs)``
Retorna um novo ``QuerySet`` contendo objetos que combinam com os
parâmetros fornecidos.
``exclude(**kwargs)``
Retorna um novo ``QuerySet`` contendo objetos que *não* combinam com os
parâmetros fornecidos.
Os parâmetros (``**kwargs`` na definição de função acima) devem estar no formato
descrito em `Campos de pesquisa`_ abaixo.
Por exemplo, para obter um ``QuerySet`` de entradas de blog do ano 2006, use o
``filter()`` desta forma::
Entry.objects.filter(pub_date__year=2006)
Nós não temos que adicionar um ``all()`` -- ``Entry.objects.all().filter(...)``.
Que continua funcionando, mas você somente precisa de ``all()`` quando deseja
obter todos os objetos do ``QuerySet`` raiz.
.. _chaining-filters:
Filtros encadeados
~~~~~~~~~~~~~~~~~~
O resultado de refinar uma ``QuerySet`` é, em si, um ``QuerySet``, então é
possível encadear refinamentos juntos. Por exemplo::
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.now()
... ).filter(
... pub_date__gte=datetime(2005, 1, 1)
... )
Isso recebe o ``QuerySet`` inicial de todas as entradas do banco de dados,
adiciona um filtro, então uma exclusão, e então um outro filtro. O resultado
final é um ``QuerySet`` contendo todas as entradas com um cabeçalho que começa
com "What", que foi publicado entre Janeiro 1, 2005 e a data atual.
.. _filtered-querysets-are-unique:
QuerySets filtrados são únicos
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cada vez que você refina um ``QuerySet``, você tem um ``QuerySet`` novo que não
é vinculado ao ``QuerySet`` anterior. Cada refinamento cria um ``QuerySet``
separado e distinto que pode ser armazenado, usado e reusado.
Exemplo::
>> q1 = Entry.objects.filter(headline__startswith="What")
>> q2 = q1.exclude(pub_date__gte=datetime.now())
>> q3 = q1.filter(pub_date__gte=datetime.now())
Este três ``QuerySet`` são separadas. O primeiro é um ``QuerySet`` base contendo
todas as entradas que contenham um cabeçalho começando com "What". O segundo é
um subconjunto do primeir, com um critério adicional que exclui dados cujo o
``pub_date`` é maior que agora. O terceiro é um subconjunto do primeiro, com um
critério adicional que seleciona somente os dados cujo ``pub_date`` é maior que
agora. O ``QuerySet`` inicial (``q1``) não é afetado pelo processo de
refinamento.
.. _querysets-are-lazy:
QuerySets são lazy
~~~~~~~~~~~~~~~~~~
Os ``QuerySets`` are lazy -- o ato de criar um ``QuerySet`` não envolve
qualquer atividade de banco de dados. Você pode empilhar filtros juntos ao longo
do dia, e o Django não os executa no banco de dados até que o ``QuerySet`` seja
*avaliado*. Dê uma olhada nesse exemplo::
>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.now())
>>> q = q.exclude(body_text__icontains="food")
>>> print q
Embora isso pareça como três hits no banco de dados, de fato o banco de dados
foi consultado somente na última linha (``print q``). Geralmente, os resultados
de um ``QuerySet`` não são buscados do banco de dados até que você "peça" por
eles. Quando você o faz, o ``QuerySet`` é *avaliado* para acessar o banco de
dados. Para mais detalhes sobre exatamente quando as avaliações tomam seu lugar,
veja :ref:`when-querysets-are-evaluated`.
Outros métodos do QuerySet
~~~~~~~~~~~~~~~~~~~~~~~~~~
Na maior parte do tempo você usará ``all()``, ``filter()`` e ``exclude()``
quando você precisar pesquisar por objetos no banco de dados. Entretanto, isso
não é tudo que há; veja a :ref:`Referência de API do QuerySet <queryset-api>`
para uma lista completa de todos os vários métodos do ``QuerySet``.
.. _limiting-querysets:
Limitando QuerySets
-------------------
Use a sintaxe de array-slicing do Python para limitar seu ``QuerySet`` com um
certo número de resultados. Este é o equivalente as clausulas SQL ``LIMIT`` e
``OFFSET``.
Por exemplo, isso retorna os primeiros 5 objetos (``LIMIT 5``)::
>>> Entry.objects.all()[:5]
Isso retorna do sexto ao décimo objeto (``OFFSET 5 LIMIT 5``)::
>>> Entry.objects.all()[5:10]
Indexação negativa (i.e. ``Entry.objects.all()[-1]``) não é suportada.
Normalmente, dividir um ``QuerySet`` resulta em um novo ``QuerySet`` -- e não
executa um nova consulta. Uma exceção é se você usa o parâmetro "step" do
Python na sintaxe do slice. Por exemplo, isso executaria na verdade a consulta
para retornar uma lista dos 10 primeiros objetos a cada *segundo*::
>>> Entry.objects.all()[:10:2]
Para receber um *único* objeto ao invés de uma lista
(e.g. ``SELECT foo FROM bar LIMIT 1``), use um index simples ao invés de um
slice. Por exemplo, isso retorna a primeira ``Entry`` do banco de dados, depois
de ordenar as entradas alfabéticamente pelos cabeçalhos::
>>> Entry.objects.order_by('headline')[0]
Isso é o equivalente a::
>>> Entry.objects.order_by('headline')[0:1].get()
Note, no entanto, que o primeiro desses será lançado ``IndexError`` enquanto o
segundo lançará ``DoesNotExists`` se nenhum objeto combinar com o critério dado.
Veja ``get()`` para mais detalhes.
.. _field-lookups-intro:
Campos de pesquisa
------------------
Campos de pesquisa são como você especifica o cerne de uma clausula ``WHERE``.
Eles são especificado como argumento nomeados para o método ``filter()`` do
``QuerySet``.
Os argumentos básicos de pesquisa tem a forma ``campo__tipodepesquisa=valor``.
(Isso é um underscore duplo). Por exemplo::
>>> Entry.objects.filter(pub_date__lte='2006-01-01')
é traduzido para o seguinte SQL::
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
.. admonition:: Como isso é possível
O Python tem a abilidade de definir funções que aceitam argumentos de
nome-valor arbitrários cujo os nomes e valores são avaliados em tempo de
execução. Para mais informações, veja `Keyword Arguments`_ no tutorial
oficial do Python.
.. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000
Se você passar um argumento inválido, uma função de pesquisa gerará o erro
``TypeError``.
A API de banco de dados suporta sobre dois dos tipos de pesquisa; uma referência
completa poe ser encontrada em :ref:`referencia dos campos de pesquisa
<field-lookups>`. Para dar a você um gosto do que está disponível, aqui temos
algumas das pesquisas mais comuns que você provavelmente usa::
:lookup:`exact`
Uma combinação "extata". Por exemplo::
>>> Entry.objects.get(headline__exact="Man bites dog")
Podria gerar o SQL ao longo dessas linhas:
.. code-block:: sql
SELECT ... WHERE headline = 'Man bites dog';
Se você não fornecer um tipo de pesquisa -- isto é, se seu argumento não
contém um underscore duplo -- o tipo de pesquisa é assumido como
``exact``
Por exemplo, as duas clausulas seguintes são equivalentes::
>>> Blog.objects.get(id__exact=14) # Forma explicita
>>> Blog.objects.get(id=14) # __exact é implícito
Isso é uma conveniência, pois pesquisas ``exact`` são um caso comum.
:lookup:`iexact`
Uma combinação não sensível a maiúsculas. Então, a consulta::
>>> Blog.objects.get(name__iexact="beatles blog")
Poderia combinar um ``Blog`` entitulado "Beatles Blog", "beatles blog",
ou mesmo "BeAtlEs blOG".
:lookup:`contains`
Sensível a maiúsculas, testa se contém. Por exemplo::
Entry.objects.get(headline__contains='Lennon')
É traduzido para este SQL:
.. code-block:: sql
SELECT ... WHERE headline LIKE '%Lennon%';
Note que combinará com cabeçalhos ``'Today Lennon honored'`` mas não
``'today lennon honored'``.
Há também uma versão não sensível a maiúsculas, :lookup:icontains`.
:lookup:`startswith`, :lookup:`endswith`
Começa com e termina com, respecitivamente. Há também a versão não
sensível a maiúsculas chamada :lookup:`istartswith` e
:lookup:`iendswith`.
De novo, estes são somente arranhões na superfície. Uma referência completa pode
ser encontrada na :ref:`referência os campos de pesquisa <field-lookups>`.
Pesquisas que abrangem relacionamentos
--------------------------------------
O Django oferece um poderoso e intuitovo meio de "seguir" relacionamentos numa
pesquisa, preocupando-se com os ``JOIN``\s SQL por vocês automaticamente, por
trás das cenas. Para abranger um relacionamento, é só usar o nome dos campos
relacionados atráves dos models, separados por dois underscores, até que você
obtenha os campos que você deseja.
Este exemplo recebe todos os objetos ``Entry`` com um ``Blog`` cujo ``name``
seja ``'Beatles Blog'``::
>>> Entry.objects.filter(blog__name__exact='Beatles Blog')
Esta abrangência pode ser tão funda quanto você quiser.
Ela funciona com backwards, também. Para referenciar um relacionamento
"reverso", é só colocar em minúsculo o nome do model.
Este exemplo recebe todos os objetos ``Blog`` que tenham pelo menos um ``Entry``
cujo ``headline`` contenha ``'Lennon'``::
>>> Blog.objects.filter(entry__headline__contains='Lennon')
Se você estiver fazendo filtragem através de vários relacionamentos e um dos
models intermediários não tiver um valor que fechar com a condição do filtro, o
Django tratará ela como se estivesse vazia (todos os valores são ``NULL``), mas
válidos. Tudo isso significa que nenhum erro será gerado. Por exemplo, neste
filtro::
Blog.objects.filter(entry__author__name='Lennon')
(se houvesse um model relacionado ``Author``), caso não houvesse nenhum
``author`` associado com uma entrada, ele poderia ser tratado como se também não
tivesse nenhum ``name`` atachado, ao invés de lançar um erro por não ter o
``author``. Normalmente este é exatamente isso que você espera que aconteça. O
único caso onde ele pode ser confuso é se você estiver usando ``isnull``. Deste
modo::
Blog.objects.filter(entry__author__name__isnull=True)
retornará objetos ``Blog`` que possuem um ``name`` vazio no ``author`` e também
aqueles que têm um ``author`` vazio sobre os ``entry``. Se você não quer esses
últimos objetos, você poderia escrever::
Blog.objects.filter(entry__author__isnull=False,
entry__author__name__isnull=True)
Abrangendo relacionamentos de múltiplos valores
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.0
Quando você está filtrando um objeto baseado no ``ManyToManyField`` ou numa
``ForeignKeyField`` reverso, há dois diferentes tipos de filtro que podem ser
interessantes. Considere o relacionamento ``Blog``/``Entry`` (``Blog`` para
``Entry`` é um relacionamento one-to-many). Nós podemos estar interessados em
encontrar blogs que tenham uma entrada que possui ambos, *"Lennon"* no título e
que foi publicado em 2008. Ou nós podemos querer encontrar blogs que tenham uma
entrada com *"Lennon"* no título bem como uma que fora publicada em 2008. Já que
há várias entradas associadas com um único ``Blog``, ambas consultas são
possíveis e fazem sentido em algumas situações.
O mesmo tipo de situação surge com um ``ManyToManyField``. Por exemplo, se uma
``Entry`` tem um ``ManyToManyField`` chamado ``tags``, nós podemos querer
encontrar entradas likadas às tags chamadas *"music"* e *"bands"* ou nós podemos
desejar uma entrada que contenha uma tag com o nome de *"musci"* e um status de
*"public"*.
Para lidar com ambas situações, o Django tem um forma consistente de
processar chamadas ``filter()`` e ``exclude()``. Tudo dentro de um única chamada
``filter()`` é aplicado simultaneamente para filtrar ítens que combinam com
todos esses requisitos. Sucessivas chamadas ``filter()`` adicionais restringem o
conjunto de objetos, mas para relações com múltiplos valores, se aplicam a
qualquer objeto linkado a primeira chamada ``filter()``.
Eles podem soar um pouco confusa, então espero que um exemplo dê uma clareada.
Para selecionar todos os blogs que contêm entradas tanto com *"Lennon"* no
título e que foram publicados em 2008 (a mesma entrada satisfazendo ambas
condições), nós escreveriámos::
Blog.objects.filter(entry__headline__contains='Lennon',
entry__pub_date__year=2008)
Para selecionar todos os blogs que contêm um entrada com *"Lennon"* no título
**bem como** uma entrada que fora publicada em 2008, nós escrevíamos::
Blog.objects.filter(entry__headline__contains='Lennon').filter(
entry__pub_date__year=2008)
Neste segundo exemplo, o primeiro filtro restringe o queryset para todos os
blogs linkados a esse tipo particular de entrada. O segundo filtro restringe o
conjunto de blogs mais as que também foram linkadas ao segundo tipo de entrada.
As entradas selecionadas no segundo filtro podem ou não, ser as mesmas entradas
do primeiro filtro. Nós estamos filtrando os ítens ``Blog`` com cada declaração
de filtro, não ítens ``Entry``.
Todo esse comportamento também é aplicado ao ``exclude()``: todas as condições
numa única declaração ``exclude()`` é aplicada a uma única instância (se estas
condições estiverem falando dessa mesma relação de múltiplos valores). Condições
em chamadas ``filer()`` ou ``exclude()`` subsequentes que referem-se ao mesmo
relacionamento podem terminar filtrando diferentes objetos linkados.
Atalho para pk
--------------
Por conveniência, o Django fornece um atalho para pesquisas com ``pk``, que
significa "chave primária".
No exemplo ``Blog`` model, a chave primária é o campo ``id``, então estas três
regras são equivalente::
>>> Blog.objects.get(id__exact=14) # Forma explicita
>>> Blog.objects.get(id=14) # __exact é implícito
>>> Blog.objects.get(pk=14) # pk implica em id__exact
O uso de ``pk`` não é limitado a consultas ``__exact`` -- qualquer termo de
consulta pode ser combinado com ``pk`` para executar uma consulta sobre a chave
primária de um model::
# Pega as entradas dos blogs com id 1, 4 e 7
>>> Blog.objects.filter(pk__in=[1,4,7])
# Pega todas as entradas do blog com id > 14
>>> Blog.objects.filter(pk__gt=14)
Pesquisas com ``pk`` também podem funcionar através de joins. Por exemplo, estas
três regras são equivalentes::
>>> Entry.objects.filter(blog__id__exact=3) # Froma explicita
>>> Entry.objects.filter(blog__id=3) # __exact é implícito
>>> Entry.objects.filter(blog__pk=3) # __pk implica em __id__exact
Escapando sinais de porcentagem e underscores em consultas LIKE
---------------------------------------------------------------
Os campos de pesquisa que equacionam consultas SQL ``LIKE`` (``iexact``,
``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith``
e ``iendswith``) terão automaticamente escapados os dois caracteres especiais
usados no ``LIKE`` -- o sinal de porcentagem e o underscore. (Numa regra
``LIKE``, o sinal de porcentagem significa um coringa de multiplos caracteres e
o underscore significa um coringa de um único caractere.)
Isso signifca que coisas devem funcionar intuitivamente, então a abstração não
vaza. Por exemplo, para receber todas as entradas que contenham um sinal de
porcentagem, é só usar o sinal de porcentagem como qualquer outro caractere::
>>> Entry.objects.filter(headline__contains='%')
O Django se encarrega de escapar para você; o SQL resultante parecerá com algo
assim:
.. code-block:: sql
SELECT ... WHERE headline LIKE '%\%%';
O mesmo serve para undescores. Ambos, sinais de porcentagem e undersocres, são
tratados para você transparentemente.
.. _caching-and-querysets:
Cacheamento e QuerySets
-----------------------
Cada ``QuerySet`` contém um cache, para minizar o acesso ao banco de dados. É
importante entender como ele funciona, a fim de se escrever um código mais
eficiente.
Num ``QuerySet`` recem criado, o cache está vazio. Na primeira vez que um
``QuerySet`` for avaliado -- e, por isso, uma consulta ao banco de dados
acontece -- o Django salva o resultado da consulta num cache de ``QuerySet`` e
retorna os resultado que foram explicitamente requisitados (e.g., o próximo
elemento, se o ``QuerySet`` estiver sendo iterado). Avaliações subsequentes de
um ``QuerySet`` reusam os resultados cacheados.
Mantenha esse comportamento de cache em mente, pois ele pode morder você se você
não usar seus ``QuerySet``\s correntamente. Por exemplo, a seguir serão criados
dois ``QuerySet``\s, eles serão avaliados, e mostrados na tela::
>>> print [e.headline for e in Entry.objects.all()]
>>> print [e.pub_date for e in Entry.objects.all()]
Isso significa que a mesma consulta ao banco de dados será executada duas
vezes, efetivamente dobrando sua carga sobre o banco de dados. Também, há a
possibilidade de duas listas que podem não incluir os mesmos dados do banco,
pois uma ``Entry`` pode ter sido adicionada ou deletada na fração de segundo que
divide as duas requisições.
Para evitar este problema, simplesmente salve o ``QuerySet`` e reuse-o::
>>> queryset = Poll.objects.all()
>>> print [p.headline for p in queryset] # Avalia o query set.
>>> print [p.pub_date for p in queryset] # Re-usa o que está em cache.
Consultas complexas com objetos Q
=================================
Consultas com palavras chaves -- no ``filter()``, etc. -- são mescladas com
"AND". Se você precisa executar consultas mais complexas (por exemplo, consultas
com ``OR``), você pode usar objetos ``Q``.
Um objeto ``Q`` (``django.db.models.Q``) é um objeto usado para encapsular uma
coleção de argumentos nomeados. Estes argumentos são especificados assim como
nos "Campos de pesquisa" acima.
Por exemplo, este objeto ``Q`` encapsula uma única consulta ``LIKE``::
Q(question__startswith='What')
Objetos ``Q`` podem ser combinados usando os operadores ``&`` e ``|``. Quando um
operador é usado em dois objetos ``Q``, ele produz um novo objeto ``Q``.
Por exemplo, esta regra produz um único objeto ``Q`` que representa o "OR" ou
duas consultas ``"question__startwith"``::
Q(question__startswith='Who') | Q(question__startswith='What')
Este é equivalente a seguinte clausula SQL ``WHERE``::
WHERE question LIKE 'Who%' OR question LIKE 'What%'
Você pode compor declarações de complexidade arbitrária combinando objetos ``Q``
com os operadores ``&`` e ``|`` e usar o agrupamento paramétrico. Também,
objetos ``Q`` podem ser negados usando o operador ``~``, permitindo combinações
entre consultas normais e negadas (``NOT``)::
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
Cada função de pesquisa que recebe argumentos nomeados (e.g. ``filter()``,
``exclude()``, ``get()``) podem também ser passados para um ou mais objetos
``Q`` como um argumento posicional. Se você fornece vários argumentos de objeto
``Q`` para uma função de pesquisa, os argumentos serão mesclados com "AND". Por
exemplo::
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
... isso se traduz aproximadamente no SQL::
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
Funções de pesquisa podem combinar o uso de objetos ``Q`` e argumentos nomeados.
Todos os argumentos fornecidos para uma função de pesquisa (sejam eles agumentos
ou objetos ``Q``) são mesclados com "AND". No entanto, se um objeto ``Q`` é
fornecido, ele deve preceder a definição de qualquer argumento nomeado.
Por exemplo::
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
... poderia ser uma consulta válida, equivalente ao exemplo anterior; mas::
# CONSULTA INVÁLIDA
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
... não seria válida.
.. seealso::
O `exemplos do OR`_ nos unit tests do Django é mostrado alguns possíveis
usos do ``Q``.
.. _exemplos do OR: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/or_lookups/models.py
Comparando objetos
==================
Para comparar duas instâncias de model, é só usar o operador de comparação
padrão do Python, dois sinais de igual: ``==``. Por trás das cenas, o que é
comparado é a chave primária dos dois models.
Usando o exemplo ``Entry`` acima, as duas declarações a seguir são
equivalentes::
>>> some_entry == other_entry
>>> some_entry.id == other_entry.id
Se uma chave primária de um model não é chamada de ``id``, não tem problema.
As comparações sempre usaram a chave primária, seja lá como for chamada. Por
exemplo, se uma chave primária de um model é chamada ``name``, estas duas
declarações são equivalentes::
>>> some_obj == other_obj
>>> some_obj.name == other_obj.name
Deletando objetos
=================
O método delete, convenientemente é chamado ``delete()``. Este método deleta
imediatamente o objeto e não retorna valor. Exemplo::
e.delete()
Você pode também deletar objetos em grupos. Todo ``QuerySet`` tem um método
``delete()``, que deleat todos os seus membros.
Por exemplo, isso deleta todos os objetos ``Entry`` com um ``pub_date`` do ano
2005::
Entry.objects.filter(pub_date__year=2005).delete()
Tenha em mente que isso irá, sempre que possível, ser executado puramente em
SQL, sendo assim o método ``delete()`` de instâncias de objeto individuais não
precisaram ser chamadas durante o processo. Se você forneceu um método
``delete()`` a uma classe model e quer se assegurar de que ele será chamado,
você precisa deletar as instâncias "manualmente" (e.g., iterando sobre o
``QuerySet`` e chamando o ``delete()`` de cada objeto individualmente) ao invés
de usar um método ``delete()`` de grupo do ``QuerySet``.
Quando o Django deleta um objeto, ele emula o comportamento de restrições
(CONSTRAINT) do SQL ``ON DELETE CASCADE`` -- em outras palavras, quaisquer
objetos que possuam uma chave estrangeira apontando ao objeto que está para ser
deletado, também será deletado com ele. Por exemplo::
b = Blog.objects.get(pk=1)
# Isso irá deletar o Blog e todos os seus objetos Entry.
b.delete()
Note que ``delete()`` é o único método de ``QuerySet`` que não é exposto num
``Manager`` em si. Este é um mecanismo de segurança para previnir que você
acidentalmente requisite ``Entry.objects.delete()``, e apague *todas* as
entradas. Se você deseja *deletar* todos os objetos, então você deve
explicitamente requisitas uma consulta completa::
Entry.objects.all().delete()
Atualizando vários objetos de uma vez
=====================================
.. versionadded:: 1.0
As vezes você quer atribuir um valor em particular a um campo de todos os
objetos de um ``QuerySet``. Você pode fazer isso com o método ``update()``.
Por exemplo::
# Atualiza todos os headlines com o pub_date em 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')
Você somente pode setar compos não relacionados e campos ``ForeignKey`` usando
este método, e o valor que você configurar o campo deve ser um valor nativo do
Python (i.e., você não pode configurar um campo para ser igual a algum outro
campo nesse momento).
Para atualizar campos ``ForeignKey``, configure o novo valor na nova instância
de model que você deseja apontar. Exemplo::
>>> b = Blog.objects.get(pk=1)
# Muda todos os Entry que pretençam a este Blog.
>>> Entry.objects.all().update(blog=b)
O método ``update()`` é aplicado instantâneamente e não retorna valores (
semelhante ao ``delte()``). A única restrição do ``QuerySet`` que foi atualizado
é que ele só pode acessar uma tabela do banco de dados, a tabela principal do
model.
Tenha cuidado que o método ``update()`` é convertido diretamente numa declaração
SQL. Ela é uma operação de massa para atualizações direta. Não executa qualquer
método ``save()`` no seus models, ou emite os sinais ``pre_save`` ou
``post_save`` (que são consequencias da chamada do ``save()``). Se você deseja
salvar todos os ítens de um ``QuerySet`` assegure-se de que o método ``save()``
seja chamada em cada instância, você não precisa de nenhuma função especial para
lidar com isso. É só iterar sobre eles e chamar o ``save()``::
for item in my_queryset:
item.save()
Objetos relacionados
====================
Quando você define um relacionamento num model (i.e., um ``ForeignKey``,
``OneToOneField``, ou ``ManyToManyField``), instâncias desse model terão uma API
conveniente para acessar os objetos relacionados.
Usando os models do topo dessa página, por exemplo, um objeto ``Entry`` ``e``
pode obter seus objetos ``Blog`` associados acessando um atributo ``blog` :
``e.blog``.
(Por trás das cenas, esta funcionalidade é implementada por descriptors_ Python.
Isso realmente não deve importar, mas nós o apontamos aqui só por curiosidade.)
O Django também cria uma API de acessores para o *outro* lado do
relacionamento -- o link de um model relacionado para outro que define o
relacionamento. Por exemplo, um objeto ``Blog`` ``b`` tem acesso a lista de
todos os objetos ``Entry`` relacionados via o atributo ``entry_set``:
``b.entry_set.all()``.
Todos os exemplos nesta seção usam as amostras de model ``Blog``, ``Author`` e
``Entry`` definidos no topo dessa página.
.. _descriptors: http://users.rcn.com/python/download/Descriptor.htm
Relacionamentos Um-para-muitos (One-to-many)
--------------------------------------------
Forward
~~~~~~~
Se um modem tem uma ``ForeignKey``, instâncias desse model terão acesso ao
objeto relacionado (foreign) via um simples atribuot do model.
Exemplo::
>>> e = Entry.objects.get(id=2)
>>> e.blog # Retorna o objeto Blog relacionado.
Você pode obter um conjunto via um atributo foreing-key. Assim como você pode
esperar, mudanças na chave estrangeira não são salvas no banco de dados até que
você chame ``save()``.
Exemplo::
>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()
Se um campo ``ForeignKey`` tem ``null=True`` (i.e., ele permite valores
``NULL``), você pode atrituir ``None`` a ele. Exemplo::
>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"
Remeter acesso a relacionamentos one-to-many é chacheado na primeira vez em que
o objeto relacionado é acessado. Subsequentes acessos a chave estrangeira do
mesmo objeto são cacheados. Exemplo::
>>> e = Entry.objects.get(id=2)
>>> print e.blog # Consluta o banco de dados para receber o Blog associado.
>>> print e.blog # Não consulta o banco de dados. usa a versão em cache.
Note que o método ``select_related()`` do ``QuerySet`` recursivamente prepopula
o cache de todos os relacionamentos one-to-many de antemão. Exemplo::
>>> e = Entry.objects.select_related().get(id=2)
>>> print e.blog # Não consulta o banco de dados; usa a versão em cache.
>>> print e.blog # Não consulta o banco de dados; usa a versão em cache.
.. _backwards-related-objects:
Seguindo os relacionamentos "backward"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Se um model tem uma ``ForeignKey``, instâncias da chave estrangeira do model
terão acesso ao ``Manager`` que retorna todas as instâncias do primeiro model.
Por padrão, esse ``Manager`` é chamado ``FOO_set``, onde ``FOO`` é o nome do
model fonte, em minusculo. Esse ``Manager`` retorna ``QuerySets``, que podem ser
filtrados e manipulados como descrito na seção "Recebendo objetos" acima.
Exemplo::
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Retorna todas os objetos Entry relacionados ao Blog.
# b.entry_set é um Manager que retorna QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()
Você pode sobrescrever o nome ``FOO_set`` através do parâmetro ``related_name``
na definição do ``ForeignKey``. Por exemplo, se o model ``Entry`` fosse alterado
para ``blog = ForeignKey(Blog, related_name='entries')``, o código do exemplo
acima ficaria::
>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Retorna todos os objetos Entry relacionados ao Blog.
# b.entries é um Manager que retorna QuerySets.
>>> b.entries.filter(headline__contains='Lennon')
>>> b.entries.count()
Você não pode acessar um ``Manager`` ``ForeignKey`` de uma classe no sentido
contrário; ele deve ser acessado de uma instância::
>>> Blog.entry_set
Traceback:
...
AttributeError: "Manager must be accessed via instance".
Além dos métodos do ``QuerySet`` definidos em "Recebendo objetos" acima, o
``Manager`` ``ForeignKey`` possui métodos adicionais utilizados para lidar com
conjuntos de objetos relacionados. Uma sinopse de cada um está abaixo, e
detalhes completos podem ser encontrados na :ref:`referência de objetos
relacionados <ref-models-relations>`.
``add(obj1, obj2, ...)``
Adiciona os objetos do model especificados ao conjunto do objeto
relacionado.
``create(**kwargs)``
Cria um novo objeto, salva-o e coloca-o no conjunto do objeto relacionado.
Retorna o novo objeto criado.
``remove(obj1, obj2, ...)``
Remove o os objetos model especificados do conjunto do objeto relacinoado.
``clear()``
Remove todos os objetos do conjunto do objeto relacionado.
Para atribuir memtros de um conjunto relacionado de uma só vez, é só atribuí-lo
de qualquer objeto iterável. O iterável pode conter instâncias de objetos, ou
só uma lista de valores de chave primária. Por exemplo::
b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]
Neste exemplo, ``e1`` e ``e2`` pode ser uma instância completa do Entry, ou
valores inteiros de chave primária.
Se o método ``clear()`` estiver disponível, quaisquer objetos pre-existentes
serão removidos do ``entry_set`` antes de todos os objetos no iterável (neste
caso, uma lista) são adicionados ao conjunto. Se o método ``clear()`` *não*
estiver disponível, todos os objetos no iterável serão adicionados sem remover
quaisquer elementos existentes.
Cada operação "reverse" descrita nesta seção tem um efeito imediato sobre o
banco de dados. Toda adição, criação e deleção é imediatamente e automaticamente
salva no banco de dados.
Relacionamentos muitos-para-muitos (Many-to-many)
-------------------------------------------------
Amdas as extremidades de um relacionamento many-to-many obtêem uma API de acesso
automática para o outro lado. A API funciona exatamente como o "backward" do
relacionamento one-to-many, acima.
A única diferença é na nomeação do atributo: O model que define o
``ManyToManyField`` usa o nome do atributo do próprio campo, considerando que o
model "reverso" usa o nome do model original em minúscula, mais ``'_set'``
(assim como reverso de relacionamentos one-to-many).
Com um exemplo fica mais fácil entender::
e = Entry.objects.get(id=3)
e.authors.all() # Retorna todos os objetos Author desta Entry.
e.authors.count()
e.authors.filter(name__contains='John')
a = Author.objects.get(id=5)
a.entry_set.all() # Retorna todos os objetos Entry desse Author.
Como ``ForeignKey``, o ``ManyToManyField`` pode especificar ``related_name``.
No exemplo acima, se o ``ManyToManyField`` em ``Entry`` tivesse especificado
``related_name='entries'``, então cada instância de ``Author`` teria um atributo
``entries`` ao invés de ``entry_set``.
Relacionamentos Um-pra-um (One-to-one)
--------------------------------------
Relacionamentos One-to-one são muito similares aos relacionamentos many-to-many.
Se você define uma :class:`~django.db.models.OneToOneField` no seu model, as
instâncias desse model terão acesso ao objeto relacionado atráves de um simples
atributo de um model.
Por exemplo::
class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField()
ed = EntryDetail.objects.get(id=2)
ed.entry # Retorna o objeto Entry relacionado.
A diferença vem nas consultas "reverse". O model relacionado num relacionamento
one-to-one também tem acesso ao objeto :class:`~django.db.models.Manager`, mas
esse :class:`~django.db.models.Manager` representa um único objeto, ao invés de
uma coleção de objetos::
e = Entry.objects.get(id=2)
e.entrydetail # retorna o objeto EntryDetail relacionado
Se nenhum objeto foi atribuído a este relacionamento, o Django lançará uma
exceção ``DoesNotExist``.
Instâncias podem ser atribuídas ao relacionamento reverso da mesma forma como
você poderia atribuir ao relacionamento forward::
e.entrydetail = ed
Como é possível relacionamentos backward?
-----------------------------------------