Fazendo consultas

Uma vez que você tenha criado seus data 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 referência do model 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:

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()
    mod_date = models.DateTimeField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    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.

See also

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:

>>> from blog.models import Author
>> 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.

Recuperando objetos

Para recuperar 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.

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.

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 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 Quando QuerySets são avaliados.

Retrieving a single object with get

.filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element.

If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly:

>>> one_entry = Entry.objects.get(pk=1)

You can use any query expression with get(), just like with filter() - again, see Campos de pesquisa abaixo.

Note that there is a difference between using .get(), and using .filter() with a slice of [0]. If there are no results that match the query, .get() will raise a DoesNotExist exception. This exception is an attribute of the model class that the query is being performed on - so in the code above, if there is no Entry object with a primary key of 1, Django will raise Entry.DoesNotExist.

Similarly, Django will complain if more than one item matches the get() query. In this case, it will raise MultipleObjectsReturned, which again is an attribute of the model class itself.

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 Referência de API do QuerySet para uma lista completa de todos os vários métodos do QuerySet.

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.

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';

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.

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 referencia dos campos de pesquisa. 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 referência os campos de pesquisa.

Pesquisas que abrangem relacionamentos

O Django oferece um poderoso e intuitovo meio de "seguir" relacionamentos numa pesquisa, preocupando-se com os JOINs 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

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.

Filters can reference fields on the model

In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?

Django provides the F() object to allow such comparisons. Instances of F() act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.

For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F() object to reference the pingback count, and use that F() object in the query:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django supports the use of addition, subtraction, multiplication, division and modulo arithmetic with F() objects, both with constants and with other F() objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

You can also use the double underscore notation to span relationships in an F() object. An F() object with a double underscore will introduce any joins needed to access the related object. For example, to retrieve all the entries where the author's name is the same as the blog name, we could issue the query:

>>> Entry.objects.filter(authors__name=F('blog__name'))
Novo no Django 1.3: Please, see the release notes

For date and date/time fields, you can add or subtract a datetime.timedelta object. The following would return all entries that were modified more than 3 days after they were published:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

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:

SELECT ... WHERE headline LIKE '%\%%';

O mesmo serve para undescores. Ambos, sinais de porcentagem e undersocres, são tratados para você transparentemente.

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 QuerySets correntamente. Por exemplo, a seguir serão criados dois QuerySets, 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.

See also

O exemplos do OR nos unit tests do Django é mostrado alguns possíveis usos do Q.

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()
Novo no Django 1.3: This cascade behavior is customizable via the on_delete argument to the ForeignKey.

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

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.

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.

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 referência de objetos relacionados.

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 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 Manager, mas esse 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?

Outro mapeador de objeto relacional requer que você defina relacionamentos em abos os lados. Os desenvolvedores do Django acreditam que isso é uma violação do princípio DRY (Don't Repeat yourself), então o Django somente requer que você defina o relacionamento de um lado.

Mas como é possível, dado que uma classe model não sabe qual outros classes model estão relacionadas até que essas outras classes sejam carregadas?

A resposta está na configuração INSTALLED_APPS. A primeira vez em que qualquer model é carregado, o Django itera sobre todos os models no INSTALLED_APPS e cria os relacionamentos backward na memória se necessário. Essencialmente, uma das funções do INSTALLED_APPS é dizer ao Django os domínios dos models.

Consultas sobre objetos relacionados

Consultas envolvendo objetos relacionados seguem as mesmas regras de consultas envolvendo campos de valores normais. Quando especificar o valor para combinar numa consulta, você pode usar tanto uma instância de objeto em si, quando o valor da chave primária do objeto.

Por exemplo, se você tem um objeto Blog b com id=5, as três consultas seguintes seriam idênticas:

Entry.objects.filter(blog=b) # Consulta usando intância de objeto
Entry.objects.filter(blog=b.id) # Consulta usando id da instância
Entry.objects.filter(blog=5) # Consulta usando id diretamente

Voltando ao SQL puro

Se você se encontrou precisando escrever uma consulta SQL que é mais complexa para o mapeador de banco de dados do Django, você pode voltar ao modo de consultas em SQL puro.

A forma preferida para fazer isso é dando ao model, métodos personalizados ou métodos personalizados ao manager, que executam consultas. Embora não há nada no Django que obrigue consultas de banco de dados estarem na camada de model, esta abordagem mantem toda a lógica de acesso a dados num único lugar, o que é mais inteligente para organização de código. Para instruções, veja Performing raw SQL queries.

Finalmente, é importante notar que a camada de banco de dados do Django é meramente uma interface para o seu banco de dados. Você pode acessar seu banco por outras ferramentas, linguagens de programação ou frameworkds de banco de dados; não há nada específico do Django sobre o seu banco de dados.