Version 10 (modified by maia, 17 years ago) ( diff )

str -> unicode



THIS TRANSLATION IS IN PROGRESS:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+-------------------------------------------------------------------------------------------------+
|    This is an **in progress** translation document, that means there is somebody working on it. |
|    For more information on translating documents please look at `TranslateDocumentation Wiki`_. |
|    Please **do not** edit this page.                                                            |
|                                                                                                 |
| .. _TranslateDocumentation Wiki : http://code.djangoproject.com/wiki/TranslateDocumentation     |
+-------------------------------------------------------------------------------------------------+   

..
  ======================
  Database API reference
  ======================

.. sidebar:: Referência da API de Banco de Dados
  :subtitle: tradução para o português.

  Documento original: `Django Database API`_
  
  Tradução: mario `<mario.caseiro at gmail.com>`
  
  Referente a revisão: 3896

.. _Django Database API: http://www.djangoproject.com/documentation/db_api/

.. contents:: **Conteúdos do capítulo**

===================================
Referência da API de Banco de Dados
===================================

Este documento cobre a versão 0.95 de Django e a versão do desenvolvimento. Docs anteriores: `0.90`_, `0.91`_



.. _0.90: http://www.djangoproject.com/documentation/0_90/ 


.. _0.91: http://www.djangoproject.com/documentation/0_91/ 

Uma vez que você criou seus `data models`_, Django fornece automaticamente uma API de abstração de banco de dados para você criar, recuperar, atualizar e deletar objetos. Este documento descreve esta API .



.. _`data models`: http://www.djangoproject.com/documentation/model_api/

Durante toda esta referência, iremos fazer referências aos modelos descritos abaixo, que compreenderiam uma aplicação de weblog.

.. code-block:: python

  class Blog(models.Model):
        name = models.CharField(maxlength=100)
        tagline = models.TextField()

        def __unicode__(self):
            return self.name

    class Author(models.Model):
        name = models.CharField(maxlength=50)
        email = models.URLField()

        def __unicode__(self):
            return self.name

    class Entry(models.Model):
        blog = models.ForeignKey(Blog)
        headline = models.CharField(maxlength=255)
        body_text = models.TextField()
        pub_date = models.DateTimeField()
        authors = models.ManyToManyField(Author)

        [imperfeita] def __unicode__(self):
            return self.name


Criando objetos
================

Para representar tabelas do banco de dados  em objetos do Python, Django usa um sistema intuitivo: Uma classe modelo representa uma tabela da banco de dados, e uma instância dessa classe representa um registro particular na tabela do banco de dados

Para criar um objeto, instancie-o usando argumentos da classe modelo, então chame ``save()`` para salva-lo no banco de dados.

Você importa a classe modelo de onde quer que ela esteja dentro do Python path, como é de se esperar. (Nós destacamos isto aqui porque em versões anteriores do Django tinhamos importações de classes modelo conturbadas.)

Assumindo que os modelos estejam em um arquivo ``mysite/blog/models.py``, segue o exemplo:: 

    from mysite.blog.models import Blog
    b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')

    b.save()

Isto executa uma declaração SQL  ``INSERT`` por baixo do panos. Django não conecta ao banco de dados até que você se chame explicitamente ``save()``. 

O método ``save()`` não retorna valor algum.

Para criar um objeto e salvá-lo, tudo em um único passo veja o método  `create`_ .

.. _`create`: http://www.djangoproject.com/documentation/db_api/#create-kwargs


Auto incrementando chaves primárias
-----------------------------------
Se um modelo tiver um ``AutoField`` -- uma chave primária auto-increment -- então o valor auto incrementado será calculado e salvo como um atributo em seu objeto na primeira vez em que você chamar ``save()``.

Exemplo::

    b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
    b2.id     # Returns None, because b doesn't have an ID yet.
    b2.save()
    b2.id     # Returns the ID of your new object.

Não há maneira alguma de dizer qual será o valor de seu ID antes de chamar ``save()``, pois o valor é obtido pelo do banco de dados, e não pelo Django.

(Para conveniência, por padrão cada modelo tem um ``AutoField`` nomeado ``id`` , a menos que você especifique explicitamente ``primary_key=True`` em um campo. Veja a documentação `AutoField`_ .) 

.. _`AutoField` : http://www.djangoproject.com/documentation/model_api/#autofield


Especificando explicitamente valores  auto-primary-key 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Caso tenha um modelo com um campo ``AutoField`` mas você queira definir o ID de um objeto explicitamente quando o salvar, é só defini-lo explicitamente antes de salvá-lo, ao invés de deixar a auto atribuição do ID.


Exemplo::

    b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
    b3.id     # Returns 3.
    b3.save()
    b3.id     # Returns 3.



Se você atribuir valores de chave-primária (auto-primary-keys)  manualmente, certifique-se de não usar um valor já existente de chave primária! Se você criar um novo objeto com um valor explícito da chave-primária que já exista no banco de dados, Django irá supor que você está mudando o registro existente ao invés de criar um novo. 

Dado o exemplo acima do blog ``'Cheddar Talk'`` , este exemplo substituiria o registro antigo do banco de dados:: 

    b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
    b4.save()  # Overrides the previous blog with ID=3!

Veja  _`Como Django decide entre UPDATE vs. INSERT`  , logo abaixo abaixo, para saber porque que isto acontece. 

Especificar valores de chaves-primárias (auto-primary-keys) explicitamente é na maior parte útil para salvar grandes quantidades de objetos, uma vez que você está seguro que não terá conflitos de chaves-primárias


Salvando alterações nos Objetos
===================================

Para salvar alterações em um objeto que já exista no banco de dados, use ``save()``. 


Dado a instância ``b5`` do ``Blog``, que já tenha sido salva no banco de dados, demonstramos no exemplo abaixo, como alterar seu nome e atualizar tal registro no banco de dados:: 

    b5.name = 'New name'
    b5.save()

Isto executa uma declaração SQL  ``INSERT`` por detrás das cenas. Django não conecta ao banco de dados até que você chame explicitamente ``save()``. 

O método ``save()`` não retorna valor algum.

Como Django decide entre UPDATE vs. INSERT
----------------------------------------------------

Você deve ter notado que os objetos de banco de dados do Django utiliza o mesmo método ``save()`` para criar e alterar objetos. Django abstrai a necessidade de utilizar declarações SQL de ``INSERT`` ou ``UPDATE``. Especificamente, quando você chama ``save()``, Django segue este algorítimo:

    * Caso o atributo chave-primária (primary-key) do objeto receba um valor que não resulte em ``False`` (assim como ``None`` ou strings vazias), Django executa uma query ``SELECT`` para determinar se já existe um registro com a chave-primária fornecida.
    * Caso já exista um registro com a chave-primária forncida, Django executa uma query de ``UPDATE``.
    * Se o atributo do chave-primária (primary-key) do objeto *não* recebeu valor algum, ou recebeu um valor que não tenha registro, Django executa um ``INSERT``.

A grande sacada aqui é que você deve ter cuidado para não especificar explicitamente um valor de chave-primária (primary-key) ao salvar novos objetos quando você não puder garantir que o valor da chave-primária (primary-key) não esteja sendo utilizado. Para mais sobre estes aspectos, ver  "Especificando explicitamente valores auto-primary-key" , acima.


Recuperando objetos
===================

Para recuperar objetos de seu banco de dados, você constrói um ``QuerySet`` através de um ``Manager`` (gerente) em sua classe de modelo. 

Um ``QuerySet`` representa uma coleção dos objetos em seu banco de dados. Pode ter zero, um ou muitos *filtros* (filters) --critérios que reduzem, estreitam a coleção baseando-se em parâmetros fornecidos. Em termos SQL, um ``QuerySet`` equivale a uma declaração ``SELECT``, e um filtro uma cláusula condicional como ``WHERE`` ou ``LIMIT``. 


Você obtém um ``QuerySet`` usando o ``Manager`` dos seus modelos (models class). Cada modelo tem pelo menos um ``Manager``, e é chamado ``objects`` por padrão. Acesse-o diretamente através das classes modelos (models classes), dessa maneira:: 

    Blog.objects  # <django.db.models.manager.Manager object at ...>
    b = Blog(name='Foo', tagline='Bar')
    b.objects     # AttributeError: "Manager isn't accessible via Blog instances."

(``Managers`` são acessívei somente por via das classes modelos, e não pelas instâncias dos modelos, isto é para garantir a separação entre operações em níveis de tabelas ("table-level") das operações em níveis de registro ("record-level") )


O ``Manager`` é a principal fonte de ``QuerySets`` para um determinado modelo (model). Ele age como uma "raiz" das ``QuerySet`` que descrevem todos os objetos em tabelas de um determinado modelo no banco de dados.
Por exemplo, ``Blog.objects`` é a ``QuerySet`` inicial que contém todos os objetos ``Blog`` no banco de dados.



Recuperando todos objetos
-------------------------

A maneira a mais simples de recuperar objetos de uma tabela é recuperá-los todos de uma vez..  Para fazer isto, use o método ``all()`` em um ``Manager``.

Exemplo::

    all_entries = Entry.objects.all()

O método ``all()`` retorna um ``QuerySet`` de todos os objetos no banco de dados.

(Já que ``Entry.objects`` é um ``QuerySet``, porque nós não podemos utilizar ``Entry.objects``?
Isto ocorre porque ``Entry.objects``, que é a ``QuerySet`` raíz , é um caso especial que não pode ser avaliado. O método ``all()`` retorna um ``QuerySet`` que *pode* ser avaliado.)

Filtrando objetos
-----------------

A ``QuerySet`` raíz que é fornecida pelo ``Manager`` descreve todos os objetos de uma tabela no banco de dados. Embora usualmente, você venha utilizar somente parte (subset) deste completo conjunto de objetos.

Para criar tal parte do conjunto, você refina a ``QuerySet`` inicial, adicionando condições como filtros. As duas maneiras mais comuns para refinar um ``QuerySet`` são: 

``filter(**kwargs)``
    Retorna um novo ``QuerySet`` contendo objetos que casam com o determinado parâmetro de busca


``exclude(**kwargs)``
    Retorna um novo ``QuerySet`` contendo objetos que *não* casam com o determinado parâmetro de busca

Os parâmetros de busca (``**kwargs`` nas funções definidas acima) devem estar no format descrito abaixo em `Field lookups`_.

.. _`Field lookups`: http://www.djangoproject.com/documentation/db_api/#field-lookups

Por exemplo, para obter um ``QuerySet`` das entradas de um blog desde o ano de 2006, use ``filter()`` dessa forma::

    Entry.objects.filter(pub_date__year=2006)

(Note que não temos que adicionar um ``all()`` -- ``Entry.objects.all().filter(...)``. Isto também deve funcionar, porém você somente precisa usar ``all()`` quando você quiser todos os objetos da ``QuerySet`` raíz.)

Filtros encadeados
~~~~~~~~~~~~~~~~~~

O resultado do refinamento de uma ``QuerySet`` é também um ``QuerySet``, assim é possível encadear outros refinamentos. Por exemplo::

    Entry.objects.filter(
        headline__startswith='What').exclude(
            pub_date__gte=datetime.now()).filter(
                pub_date__gte=datetime(2005, 1, 1))

...observe o ``QuerySet`` inicial com todas entradas contidas no banco de dados, inclua um filtro, depois uma exclusão, e depois outro filtro. O resultado final é um ``QuerySet`` contendo todas as entradas que o cabeçalho (headline) começe com "What", que foram publicados entre 1 de janeiro de 2005 e a data atual.

QuerySets filtrados são únicos
------------------------------

Cada vez que você refina um ``QuerySet``, você recebe um novo ``QuerySet``  que de nenhuma maneira limita (influencía)  o ``QuerySet`` anterior. Cada refinamento cría um ``QuerySet`` separado e distinto que pode ser armazenado, usado e reutilizado. 

Exemplo::

    q1 = Entry.objects.filter(headline__startswith="What")
    q2 = q1.exclude(pub_date__gte=datetime.now())
    q3 = q1.filter(pub_date__gte=datetime.now())

Estes três ``QuerySets`` estão separados. O primeiro é um ``QuerySet`` base contendo todas as entradas que possuem um cabeçalho (headline) que começa com ?What?. O segundo é um subconjunto do primeiro, com critérios adicionais que exclui os registros cujo ``pub_date`` são maiores do que a data atual. O terceiro é um subconjunto do primeiro, com critérios adicionais que selecionam somente os registros cujo ``pub_date`` são maiores que a data atual. O ``QuerySet`` inicial  (``q1``) não é afetado pelo processo do refinamento. 


QuerySets são preguiçosas
-------------------------

``QuerySets`` são preguiçosas -- o ato de criar um ``QuerySet`` não envolve nenhuma atividade no banco de dados. Você pode utlizar filtros e mais filtros durante todo o dia e Django não rodará uma só query até que o ``QuerySet`` seja *assimilado*. 


Quando QuerySets são assímilados
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Você pode avaliar um ``QuerySet`` nas seguintes situações: 

    * **Iteration.** O ``QuerySet`` é iterativo, e executa sua query no banco de dados na primeira vez que você itera sobre ele. Por exemplo, isto imprimirá o cabeçalho (headline) de todas as entradas no banco de dados:: 


          for e in Entry.objects.all():
              print e.headline

    * **Slicing.** Como explicado em `Limitando QuerySets`_ logo abaixo, um ``QuerySet``  pode ser dividido em parcelas, usando a sintaxe para extrair parcelas de array do Python. Geralmente cortar (extrair uma parcela) um ``QuerySet`` retorna outro (não avaliado / unevaluated) ``QuerySet``, mas Django executará a query no banco de dados se você usar o parâmetro ?step? da sintaxe de extrair parcelas. 

    * **repr().** Um ``QuerySet`` está avaliado quando você chama ``repr()`` nele. Isto é para a conveniência do interpretador interativo do Python, assim você pode imediatamente ver seus resultados ao usar a API interativamente. 

    * **len().** Um ``QuerySet`` está avaliado quando você chamada ``len()`` nele. Isto, como é de se esperar, retorna o comprimento da lista resultante. 

      Nota: *Nào* use ``len()`` em ``QuerySet``\s se tudo que você quer fazer for  determinar o número dos registros no conjunto. É muito mais eficiente manipular uma contagem no nível de banco de dados, usando SQL ``SELECT CONT(*)``, e Django fornece um método ``cont()`` precisamente por esta razão. Ver o ``cont()`` abaixo. 

    * **list().** Força ser avaliado um ``QuerySet`` chamando``list()`` nele. Por exemplo::

          entry_list = list(Entry.objects.all())

      Contudo esteja ciente,  isto pode causar um grande overhead de memória, porque Django carregará cada elemento da lista na memória. Por sua vez, iterar sobre um``QuerySet`` tomará vantagem de seu banco de dados para carregar dados e instanciar objetos somente quando você os necessita. 

Limitando QuerySets
-------------------

Use a syntax de extração de parcelas de arrays do  Python para limitar o seu ``QuerySet`` para um certo número de resultados. Isto é o equivalente das cláusulas SQL ``LIMIT`` e ``OFFSET``.

Por exemplo, isto retorna os 5 primeiros objetos(``LIMIT 5``)::

    Entry.objects.all()[:5]

Isto retorna do quinto ao decimo objeto(``OFFSET 5 LIMIT 5``)::

    Entry.objects.all()[5:10]

Geralmente, extrair parcelas de um ``QuerySet`` retorna um ``QuerySet``  novo -- não avalía (executa) a query. Uma exceção é se você usar o parâmetro de ?step? da sintaxe da extração de parcelas do Python. Por exemplo, isto executaria realmente a query a fim de retornar uma lista de cada *segundo* objeto dos primeiros 10:: 

    Entry.objects.all()[:10:2]


Para recuperar um *único* objeto ao invés de uma lista  (por exemplo ``SELECT foo FROM bar LIMIT 1``), use simplismente um índice em vez de uma parcela (sclice). Por exemplo, isto retorna a primeira ``Entry`` no banco de dados, após ordenar entradas alfabeticamente pelo cabeçalho (headline):: 

    Entry.objects.order_by('headline')[0]

Isto é aproximadamente equivalente a:: 

    Entry.objects.order_by('headline')[0:1].get()

Note, entretanto, que o primeiro destes levantará ``IndexError`` equanto o segundo levantará ``DoesNotExist`` se nenhum objeto combinar os critérios dados. 

Método de QuerySet que retornam novos QuerySets
-----------------------------------------------

Django fornece uma gama de métodos para refinamento de ``QuerySet`` que modificam ou os tipos de resultados retornados pelo ``QuerySet`` ou a maneira sua query SQL é executada. 

``filter(**kwargs)``
~~~~~~~~~~~~~~~~~~~~

Retorna um novo``QuerySet`` contendo objetos que casam com o determinado parâmetro de busca

Os parâmetros de busca (``**kwargs``) devem estar no formato descrito em `Field lookups`_ logo abaixo. Múltiplos parametros são juntados via ``AND`` na declaração SQL subjacente.

``exclude(**kwargs)``
~~~~~~~~~~~~~~~~~~~~~

Retorna um novo``QuerySet`` contendo objetos que *não* casam com o determinado parâmetro de busca

Os parâmetros de busca (``**kwargs``) devem estar no formato descrito em `Field lookups`_ logo abaixo. Múltiplos parâmetros são juntados via ``AND`` na declaração SQL subjacente, e tudo isto  delimitado por ``NOT()``.




Este exemplo exclue todas entradas que ``pub_date`` é a date/time corrente  E (AND) aqueles que o cabeçalho (``headline``) é  "Hello"::

    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

em termos SQL, isto é assimilado como::

    SELECT ...
    WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

Este exemplo excluí todas entradas que ``pub_date`` é a date/time corrente OU (OR) aqueles que o cabeçalho (``headline``) é  "Hello"::

    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')


em termos SQL, isto é assimilado como::

    SELECT ...

    WHERE NOT pub_date > '2005-1-3' AND NOT headline = 'Hello'

Note que o segundo exemplo é mais restritivo.


``order_by(*fields)``
~~~~~~~~~~~~~~~~~~~~~

Por padrão, os resultados retornados por um ``QuerySet`` são ordenados pela tupla dada na opção ``ordering`` no ``Meta`` do modelo. Você pode sobrescrever isto em  um ``QuerySet`` usando o método ``order_by``. 

Exemplo::

    Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

O resultado acima será ordenado por ``pub_date`` decresente, então por ``headline`` crescente. O sinal negativo na frente de ``"-pub_date"`` indica a ordem *decrescente*. A ordem Crescente é implícita. Para requisitar aleatòria, use ``"?"``, como assim:: 

    Entry.objects.order_by('?')

Para ordenar por um campo de uma tabela diferente, adicione o nome da outra tabela e um ponto , assim como:: 

    Entry.objects.order_by('blogs_blog.name', 'headline')

Não há nenhuma maneira de especificar se a Ordenação deve ser "case sensitive". Com respeito à "case sensitive", Django ordenará os resultados apesar do backend de que seu banco de dados normalmente já os ordene . 


``distinct()``
~~~~~~~~~~~~~~



Retorna um novo ``QuerySet`` que utiliza ``SELECT DISTINCT`` na query SQL. Isto elimina linhas duplicadas dos resultados da query.

Por padrão, um``QuerySet`` não irá eliminar linhas duplicadas. Na prática, isto  raramente é um problema, porque as querys simples tais como ``Blog.objects.all()`` não introduzem no resultado a possibilidade de linhas duplicadas. 

Entretanto, se sua query refere-se a múltiplas tabelas , é possível obter resultados duplicados quando um ``QuerySet`` é assimilado. Este é o caso de quando você deveria usar ``distinct()``. 

``values(*fields)``
~~~~~~~~~~~~~~~~~~~

Retorna um ``ValuesQuerySet`` -- um ``QuerySet`` que assimila uma lista de dicionários ao invés do modelo-instância de objetos. 

Cada um daqueles dicionários representa um objeto, com as chaves que correspondem aos nomes dos atributos dos objetos de modelo. 

Este exemplo compara os dicionários de ``values()`` com os objetos de modelo normais:: 

    # Esta lista contem um objeto de Blog .
    >>> Blog.objects.filter(name__startswith='Beatles')
    [Beatles Blog]

    # Esta lista contem um dicionário.
    >>> Blog.objects.filter(name__startswith='Beatles').values()
    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

``values()`` leva argumentos de posições opcionais, os ``*fields``, que especifica  nomes dos campos a que  ``SELETO`` deve se limitar. Se você especificar os campos, cada dicionário conterá somente as chaves/valores dos campos  que você especificou. Se você não especificar os campos, cada dicionário conterá uma chave e um valor para cada campo na tabela do banco de dados. 

Exemplo::

    >>> Blog.objects.values()
    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
    >>> Blog.objects.values('id', 'name')
    [{'id': 1, 'name': 'Beatles Blog'}]

Um ``ValuesQuerySet`` é útil quando você sabe que você necessitará somente valores de um pequeno número de campos disponíveis e você não necessitará  a funcionalidade da instância de um objeto de modelo. É mais eficiente selecionar somente os campos que você necessita usar. 

Finalmente, note que um ``ValuesQuerySet`` é uma subclasse de ``QuerySet``, assim possui todos os métodos de ``QuerySet``. Você pode chamar ``filter()`` nele, ou ``order_by()``, ou outro método qualquer. Sim, isso significa que estas duas chamadas são idênticas:: 

    Blog.objects.values().order_by('id')
    Blog.objects.order_by('id').values()

As pessoas que fizeram Django preferem pôr todos os métodos SQL de alterações primeiro, seguido (opcionalmente) por quaisquer métodos de manipulem saída (tais como ``values()``), mas isso não importa realmente. Esta é sua oportunidade de realmente "flaunt" seu individualismo. 

``dates(field, kind, order='ASC')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Retorna um ``DateQuerySet`` -- um ``QuerySet`` que assimila uma lista de  ``datetime.datetime`` objetos representando todas as datas disponíveis de um tipo particular dentro dos conteúdos do ``QuerySet``. 

``field`` deve ser o nome de um ``DateField`` ou ``DateTimeField`` de seu modelo

``tipo`` (kind) deve ser tanto ``"year"``, ``"month"`` ou ``"day"``. Cada ``datetime.datetime`` objeto na lista resultante é truncado ("truncated") ao tipo (``type``) fornecido.

    * ``"year"`` retorna uma lista de todos os valores distintos de ANOS para o campo.
    * ``"month"`` retorna uma lista de todos os valores distintos de MESES para o campo.
    * ``"day"`` retorna uma lista de todos os valores distintos de DIAS para o campo.

``order``, que por padrão é ``'ASC'``, deve ser tanto ``'ASC'`` (crescente) ou ``'DESC'`` (decrescente). Isto especifica a ordem dos resultados.

Exemplos::

    >>> Entry.objects.dates('pub_date', 'year')
    [datetime.datetime(2005, 1, 1)]
    >>> Entry.objects.dates('pub_date', 'month')
    [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]
    >>> Entry.objects.dates('pub_date', 'day')
    [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]
    >>> Entry.objects.dates('pub_date', 'day', order='DESC')
    [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]
    >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
    [datetime.datetime(2005, 3, 20)]

``select_related()``
~~~~~~~~~~~~~~~~~~~~
Retorna um ``QuerySet`` que automaticamente "segue"  os relacionamentos de chave-estrangeira, selecionando os dados adicionais do objeto-relacionado quando executa a query. Este é um impulsionador de desempenho que resulta  em querys (às vezes, muito)maiores mas o uso posterior dos relacionamentos de chave-estrangeiras não requerem novas queries no banco de dados. 

Os seguintes exemplos ilustram a diferença entre buscas simples e buscas ``select_related()``. Está aqui a busca padrão:: 

    # Aciona o banco de dados.
    e = Entry.objects.get(id=5)

    # Aciona o banco de dados novamente para obter o objeto Blog relacionado.
    b = e.blog

Agora a busca ``select_related`` ::

    # Aciona o banco de dados.
    e = Entry.objects.select_related().get(id=5)

    # Não aciona o banco de dados, porque e.blog já foi previamente populado na query anterior.
    b = e.blog

``select_related()`` segue as chaves-estrangeiras tão longe quanto possível. Se você tiver os seguintes modelos:

    class City(models.Model):
        # ...

    class Person(models.Model):
        # ...
        hometown = models.ForeignKey(City)

    class Book(models.Model):
        # ...
        author = models.ForeignKey(Person)

...então chamar ``Book.objects.select_related().get(id=4)`` irá fazer um cache da pessoa (``Person``) relacionada *e* da cidade (``City``) relacionada::

    b = Book.objects.select_related().get(id=4)
    p = b.author         # Não aciona o banco de dados.
    c = p.hometown       # Não aciona o banco de dados..

    sv = Book.objects.get(id=4) # Sem select_related() neste exemplo.
    p = b.author         # Aciona o banco de dados.
    c = p.hometown       # Aciona o banco de dados.

Note que ``select_related()`` não segue chaves-estrangeiras que tenham ``null=True``.

``extra(select=None, where=None, params=None, tables=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Às vezes, a sintaxe de query do Django por sí não pode fàcilmente expressar uma cláusula ``WHERE`` complexa. Para estes casos limitados, Django fornece o modificador de ``QuerySet`` ``extra()``-- uma brecha para injetar cláusulas específicas no SQL gerado pelo ``QuerySet``. 

Por definição, estas buscas extras podem não ser portáveis aos diferentes engines de banco de dados (porque você está escrevendo explicitamente um código SQL) e viola o princípio DRY, assim você deve evitá-los sempre que possível. 


Especifique um ou mais dos seguintes ``params``, ``select``, ``where`` ou ``tables``. Nenhum dos argumentos é requerido, mas você deve usar pelo menos um deles. 

``select``
    The ``select`` argument lets you put extra fields in the ``SELECT`` clause.
    It should be a dictionary mapping attribute names to SQL clauses to use to
    calculate that attribute.

    Exemplo::

        Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})


    Como resultado, cada objeto ``Entry`` terá um atributo extra, ``is_recent``, uma representação booleana de  ``pub_date`` de entrada é maior do que janeiro 1, 2006.

    Django insere o trecho SQL dado diretamente na declaração ``SELECT``, assim a SQL resultante do exemplo acima seria::

        SELECT blog_entry.*, (pub_date > '2006-01-01')
        FROM blog_entry;


    O exemplo seguinte é mais avançado; faz uma subquery para dar a cada objeto ``Blog`` resultante um atributo ``entry_count``, um inteiro da contagem de objetos associados da ``Entry``::

        Blog.objects.extra(
            select={
                'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
            },
        )

    (Neste caso particular, nós estamos abusando do fato que a query já conterá a tabela ``blog_blog`` no sua cláusula ``FROM`` .)

O SQL resultante do exemplo acima seria::

        SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id)
        FROM blog_blog;

Note que o parênteses requerido pela maioria dos engines de banco de dados ao redor das subqueries não são requeridos nas cláusulas ``select`` do Django . Note também que alguns backends de banco de dados , como algumas versões de MySQL, não suportam subqueries.

``where`` / ``tables``
    Você pode definir as cláusulas SQL ``WHERE`` explícitamente  -- talvez para executar joins não-explícitos -- usando ``where``. Pode também manualmente adicionar tabelas a cláusula  SQL ``FROM`` usando ``tables``.

    ``where`` e ``tables`` ambos levam uma lista de strings. Todos parâmetros ``where``  são adicionados de "AND" para qualquer outro critério de busca.

    Exemplo::

        Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])

    ...traduz (aproximadamente) na seguinte SQL::

        SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);


``params``
    Os parâmetros  ``select`` e ``where`` descritos acima podem usar o padrão de placeholders de string para banco de dados do Python -- ``"%s"`` para indicar parâmetros que o engine de banco de dados deve adicionar  automaticamente aspas. O argumento ``params`` é uma lista de todos os parâmetros extra a serem substituídos.
        

    Exemplo::

        Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

    Sempre  use ``params`` em vez de encaixar valores diretamente em ``select`` ou ``where`` porque os ``params`` assegurarão que os valores sejam adcionados de aspas corretamente de acordo com seu backend. (Por exemplo, as aspas serão escapadas corretamente.)

    Ruim::

        Entry.objects.extra(where=["headline='Lennon'"])

    Bom::

        Entry.objects.extra(where=['headline=%s'], params=['Lennon'])


Note: See TracWiki for help on using the wiki.
Back to Top