 | Nível: Intermediário Liza Daly, Software Engineer and Owner, Threepress Consulting Inc.
19/Mai/2009 Após se graduarem do wiki de cinco minutos para os aplicativos da vida real, os programadores do Django podem
criar facilmente classes de modelos confusas, difíceis de manter ou ineficientes. Saiba como evitar erros de consulta
comuns, utilizar gerenciadores de modelo para encapsular consultas complexas e tirar proveito dos poderosos novos recursos
de agregação disponíveis no Django V1.1.
No Django, a maioria das interações com um banco de dados é através de seu Object-Relational Mapper (ORM), um recurso
que o Django compartilha com outras estruturas recentes da Web, como Rails. ORMs são cada vez mais populares entre os
desenvolvedores, já que automatizam muitas interações comuns com um banco de dados e utilizam abordagens familiares
orientadas a objetos no lugar de instruções SQL.
Os programadores do Django podem optar por ignorar o ORM nativo em benefício do popular pacote
SQLAlchemy, mas embora o SQLAlchemy seja totalmente poderoso, ele
também é muito mais difícil de ser usado e requer mais linhas de código. Os aplicativos Django podem ser e são desenvolvidos
com o uso de SQLAlchemy em vez de ORM nativo, mas alguns dos recursos mais atraentes do Django,
como sua interface administrativa gerada automaticamente, requerem o uso do ORM.
 |
Acrônimos Usados Frequentemente
- API: Interface de Programação de Aplicativos
- HTML: Linguagem de Marcação de Hipertexto
- RDBMS: Sistema de Gerenciamento de Banco de Dados Relacional
- SQL: Linguagem de Consulta Estruturada
|
|
Este artigo esclarece alguns dos recursos menos conhecidos do ORM do Django em particular, mas os usuários do
SQLAlchemy podem encontrar algumas instruções de cuidado sobre a geração de consulta
ineficiente aplicável ao seu próprio código.
As versões de software utilizadas neste artigo incluem:
- Django V1.0.2 (partes 1 e 2)
- Django V1.1 alpha (parte 3)
- sqlite3
- Python V2.4-2.6 (Django ainda não suporta Python V3.)
- IPython (para a saída de amostra)
O ORM do Django suporta muitos back ends de banco de dados, mas o sqlite3 é o mais fácil de instalar e é fornecido
em um pacote configurável com vários sistemas operacionais. Esses exemplos devem funcionar com qualquer back end. Para
obter uma lista dos bancos de dados suportados pelo Django, consulte Recursos.
Evitando Traps Comuns na Geração de Consulta do ORM
O design do Django estimula um estilo de desenvolvimento ágil que recompensa a criação de protótipos e experimentos
rápidos. Nos primeiros estágios, é melhor não se preocupar com o desempenho e, em vez disso, favorecer a capacidade de
leitura e a facilidade de implementação.
Às vezes, não demora muito tempo para ocorrer um problema de desempenho. Muitas vezes, isso acontece na primeira vez
que você experimenta seu aplicativo com dados reais. Às vezes, isso fica óbvio quando a execução do conjunto de testes
se arrasta até a marca dos cinco minutos, mas contém apenas alguns testes. Outras vezes, o aplicativo está apenas
visivelmente lento. Felizmente, existem alguns padrões facilmente identificáveis que são também fáceis de corrigir. Um
caso comum é mostrado na Listagem 1 (o arquivo models.py do aplicativo) e Listagem 2.
Listagem 1. Modelos Básicos para o Aplicativo de Exemplos: models.py
from django.db import models
# Algum tipo de documento, como uma postagem em um log ou uma página de um wiki
class Document(models.Model):
name = models.CharField(max_length=255)
# Um comentário gerado pelo usuário, como localizado em um site como
# Digg ou Reddit
class Comment(models.Model):
document = models.ForeignKey(Document, related_name='comments')
content = models.TextField()
|
 |
Sobre as Amostras de Código
O Django fornece um atalho acessível para a configuração de um ambiente de trabalho em código independente: através
da execução do shell python manage.py. Todas as amostras de código neste artigo pressupõem que
o ambiente tenha sido invocado dessa forma.
Neste artigo de linguagem Django, supõe-se o seguinte:
- O projeto Django é chamado better_models.
- O projeto better_models contém um aplicativo chamado examples.
O aplicativo examples modela um sistema básico em forma de blog de documentos e zero ou mais comentários sobre esses
documentos.
|
|
A Listagem 2 mostra como acessar os modelos configurados na Listagem 1 de maneira ineficiente.
Listagem 2. Acessando estes Modelos de Forma Muito Lenta
from examples.model import *
import uuid
# Primeiro crie vários documentos e designe a eles nomes aleatórios
for i in range(0, 10000):
Document.objects.create(name=str(uuid.uuid4()))
# Faça uma seleção de nomes para ser consultada depois
names = Document.objects.values_list('name', flat=True)[0:5000]
# Uma forma realmente lenta de se obter uma lista de Documentos que
# correspondem a esses nomes
documents = []
for name in names:
documents.append(Document.objects.get(name=name))
|
Este é um exemplo elaborado, mas ilustra um caso de uso bastante comum: Dada uma lista de identificadores, obtenha
todos os itens que correspondem a esses identificadores do banco de dados.
O exemplo acima codificado com simplicidade levou 65 segundos para ser executado com o uso do sqlite3 na memória. Com um
banco de dados dependente de sistema de arquivos, ele levaria muito mais tempo. Entretanto, a Listagem 3 possui uma correção
para esta consulta de execução lenta. Em vez de emitir várias consultas de banco de dados para cada valor de nome, utilize o
operador fieldname__in para gerar uma consulta SQL semelhante à:
SELECT * FROM model WHERE fieldname IN ('1', '2', ...)
|
(A sintaxe de consulta real gerada irá variar por mecanismo de banco de dados.)
Listagem 3. Uma Consulta Rápida para se Obter uma Lista de Itens
from examples import models
import uuid
for i in range(0, 10000):
Document.objects.create(name=str(uuid.uuid4()))
names = Document.objects.values_list('name', flat=True)[0:5000]
documents = list(Document.objects.filter(name__in=names))
|
Esse código é executado em apenas 3 segundos. Observe que esse código lança o resultado da consulta para uma lista
para forçar a avaliação da consulta. Como as consultas do Django são avaliadas lentamente, a simples designação do
resultado da consulta não causaria a ocorrência de nenhum acesso ao banco de dados, invalidando a comparação.
Os mestres em bancos de dados podem achar este exemplo óbvio, principalmente se eles estiverem acostumados a gravar
SQL bruta, mas muitos programadores de Python não têm conhecimento em banco de dados.
Às vezes, os melhores instintos dos programadores podem, de fato, funcionar com eficiência. A Listagem 4 demonstra uma
maneira em que você pode optar por refatorar o código na Listagem 2, e a não constatação disso pode se tornar um trap.
Listagem 4. Um Padrão Comum Resultando em Uso do Banco de Dados Lento
for name in names:
documents.append(get_document_by_name(name))
def get_document_by_name(name):
return Document.objects.get(name=name))
|
Superficialmente, pode parecer uma boa ideia criar um método separado para a recuperação de documentos do banco de
dados. Talvez haja outro trabalho que deveria ser feito aqui, como a inclusão de dados no modelo antes de retorná-lo. Preste
atenção a este padrão, pois a refatoração em métodos discretos pode parecer um aprimoramento no código. A gravação de testes
de unidade desde o começo do desenvolvimento e a inclusão de pelo menos alguns testes que operam em grandes conjuntos de dados
podem ajudar a identificar quando a refatoração resultar em quedas de desempenho repentinas.
Encapsulando Consultas Comuns com Modelos de Gerenciador
Todos os desenvolvedores do Django utilizam a classe Manager integrada: Isso é o que é
chamado para todos os métodos na forma Model.objects.*. A classe base Manager
fica disponível automaticamente e fornece os métodos utilizados com mais frequência que retornam QuerySets
(por exemplo, all()), aqueles que retornam valores (por exemplo, count()) e
aqueles que retornam instâncias Model (por exemplo, get_or_create()).
Os desenvolvedores do Django são incentivados a substituírem a classe base Manager. Para
ilustrar a razão pela qual este recurso é útil, estenda o aplicativo examples para incluir um novo modelo, Format,
que descreve o formato do arquivo dos documentos no sistema. Um exemplo é mostrado abaixo.
Listagem 5. Incluindo um Modelo no Examples
from django.db import models
class Document(models.Model):
name = models.CharField(max_length=255)
format = models.ForeignKey('Format')
class Comment(models.Model):
document = models.ForeignKey(Document, related_name='comments')
content = models.TextField()
class Format(models.Model):
type = models.CharField(choices=( ('Text file', 'text'),
('ePub ebook', 'epub'),
('HTML file', 'html')),
max_length=10)
|
 |
Melhores Práticas para Atualizações de Bancos de Dados
Sempre que incluir tabelas ou colunas em models.py, é necessário ressincronizar o banco de dados relacionado. Existem
algumas boas práticas para isso:
- No desenvolvimento inicial, utilize um banco de dados em memória como sqlite3 apenas e empregue instalações de
bancos de dados para carregar automaticamente o conteúdo de amostra. Os bancos de dados em memória podem ser absolutamente
rápidos para um único usuário e podem reduzir muito o tempo de espera para eliminação e recriação de tabelas em um RDBMS
tradicional como MySQL.
- Utilize uma abordagem de desenvolvimento orientada a testes. A estrutura de testes do Django recria seu banco de
dados do zero toda vez, portanto, as tabelas estão sempre atualizadas. A combinação dessa funcionalidade com os bancos de
dados em memória sqlite3 torna os testes muito mais rápidos.
- Experimente um dos muitos complementos do Django que gerenciam a sincronização do banco de dados. Eu tive boas
experiências com o pacote
django-evolution, mas também existem outros. Para obter informações adicionais sobre django-evolution, consulte Recursos.
Se você optar por utilizar sqlite3 em seu desenvolvimento ou teste, certifique-se de executar os testes de integração
finais com seu banco de dados de produção. O ORM do Django ajuda a amenizar as diferenças entre os mecanismos RDBMS para
os casos mais comuns, mas não há garantia de que todos os comportamentos sejam idênticos.
|
|
Em seguida, utilize os modelos alterados para criar alguns documentos de amostra com instâncias Format
designadas.
Listagem 6. Criar alguns Documentos com Formatos Designados
# Primeiro crie uma série de objetos Format e salve-os
no banco de dados
format_text = Format.objects.create(type='text')
format_epub = Format.objects.create(type='epub')
format_html = Format.objects.create(type='html')
# Crie alguns documentos em vários formatos
para i no intervalo (0, 10):
Document.objects.create(name='My text document',
format=format_text)
Document.objects.create(name='My epub document',
format=format_epub)
Document.objects.create(name='My HTML document',
format=format_html)
|
Imagine que esse aplicativo fornecerá uma maneira de se filtrar primeiro os documentos por formato, depois filtrar
QuerySet por outros campos, como título. A seguir temos uma consulta simples para retornar
apenas os documentos de texto: Document.objects.filter(format=format_text).
Nesse exemplo, o significado da consulta está claro, mas em um aplicativo maduro, talvez você precise aplicar muito
mais restrições ao conjunto de resultados. Talvez você queira restringir a listagem apenas aos documentos marcados como públicos ou
documentos com mais de 30 dias de existência. Se você tiver que chamar essa consulta de vários locais em seu aplicativo,
manter todas as cláusulas de filtro em sincronia pode se tornar um problema de manutenção e uma fonte de erros reais.
É aí que um gerenciador customizado pode ajudar. Os gerenciadores customizados oferecem a capacidade de definir
números ilimitados de consultas "pré-determinadas" — semelhantes aos métodos de gerenciador integrados, como latest() (que
retorna apenas a instância mais recente de um determinado modelo) ou distinct() (que emite
uma cláusula SELECT DISTINCT na consulta gerada).
Essas consultas não só reduzem a quantidade de código que pode precisar ser duplicada em seus aplicativos, mas os
gerenciadores melhoram a capacidade de leitura. Com o tempo, talvez você prefira ler isto:
Documents.objects.filter(format=format_text,publish_on__week_day=todays_week_day,
is_public=True).distinct().order_by(date_added).reverse()
|
Ou talvez seja mais fácil para você ou um novo desenvolvedor entender:
Documents.home_page.all()
|
Criar um gerenciador customizado é extremamente simples. A Listagem 7 mostra o exemplo get_by_format.
Listagem 7. Classe do Gerenciador Customizado que Fornece Métodos para cada Tipo de Formato
from django.db import models
class DocumentManager(models.Manager):
# A classe do modelo para este gerenciador está sempre disponível como
# self.model, mas neste exemplo, estamos contando apenas com o
# método filter() herdado de models.Manager.
def text_format(self):
return self.filter(format__type='text')
def epub_format(self):
return self.filter(format__type='epub')
def html_format(self):
return self.filter(format__type='html')
class Document(models.Model):
name = models.CharField(max_length=255)
format = models.ForeignKey('Format')
# O novo gerenciador de modelo
get_by_format = DocumentManager()
# O gerenciador de modelo padrão agora precisa ser explicitamente definido
objects = models.Manager()
class Comment(models.Model):
document = models.ForeignKey(Document, related_name='comments')
content = models.TextField()
class Format(models.Model):
type = models.CharField(choices=( ('Text file', 'text'),
('ePub ebook', 'epub'),
('HTML file', 'html')),
max_length=10)
def __unicode__(self):
return self.type
|
Alguns comentários sobre esse código:
- Se você definir um gerenciador customizado, o Django removerá automaticamente o gerenciador padrão. Eu prefiro
deixar o gerenciador padrão e o gerenciador customizado para que outros desenvolvedores (ou eu mesmo, quando eu me esquecer)
possam utilizar
objects e para que ele se comporte exatamente como esperado. Entretanto,
como meu novo gerenciador get_by_format é apenas uma subclasse do models.Manager
do Django, todos os métodos padrão, como all() estão disponíveis para ele. Se você vai incluir o
gerenciador padrão, bem como o gerenciador customizado, é uma preferência sua.
- Também é possível designar seu novo gerenciador ao
objects
diretamente. Existe uma única desvantagem caso você queira substituir o QuerySet em si inicial. Seu novo objects terá um comportamento inesperado podendo não ser previsto por outros desenvolvedores.
- Você precisa definir a classe do gerenciador em models.py antes de definir sua classe de modelo, ou a classe não
estará disponível para o Django. Isso é semelhante às restrições em torno das referências da classe
ForeignKey.
- Eu poderia simplesmente ter implementado
DocumentManager
com um único método que utiliza um argumento, como with_format(format_name). Geralmente, eu
prefiro os métodos do gerenciador que possuem nomes de métodos detalhados, mas não utilizam argumentos.
- Não existe um limite técnico para o número de gerenciadores customizados que você pode designar a uma classe,
mas provavelmente você não precisará mais de dois.
É muito simples utilizar os novos métodos do gerenciador.
In [1]: [d.format for d in Document.get_by_format.text_format()][0]
Out[1]: <Format: text>
In [2]: [d.format for d in Document.get_by_format.epub_format()][0]
Out[2]: <Format: epub>
In [3]: [d.format for d in Document.get_by_format.html_format()][0]
Out[3]: <Format: html>
|
Agora existe um lugar conveniente para a interrupção de qualquer funcionalidade relacionada a essas consultas, e você
pode aplicar restrições adicionais sem atravancar o código. E também, acompanhar o estilo da marca de model view controller
(MVC) do Django de colocar esse tipo de funcionalidade no arquivo models.py em vez de jogá-la em visualizações ou tags
de modelos.
Substituindo o QuerySet Inicial Retornado por um Gerenciador Customizado
Outro padrão de codificação que pode ser aplicado às classes de gerenciador é um que pode não ter absolutamente
nenhum método customizado. Em vez de definir um novo método que retorne apenas documentos no formato HTML, por exemplo,
você poderia definir um gerenciador customizado que opere totalmente nessa configuração restrita, como o mostrado
abaixo.
Listagem 8. Gerenciador Customizado para Documentos HTML
class HTMLManager(models.Manager):
def get_query_set(self):
return super(HTMLManager, self).get_query_set().filter(format__type='html')
class Document(models.Model):
name = models.CharField(max_length=255)
format = models.ForeignKey('Format')
html = HTMLManager()
get_by_format = DocumentManager()
objects = models.Manager()
|
O método get_query_set() é herdado de models.Manager e é
substituído nesse exemplo para pegar a consulta básica (a mesma que o all()
gera) e aplicar o filtro adicional a ela. Quaisquer métodos subsequentes que você incluir neste gerenciador chamarão
o método get_query_set() primeiro e depois aplicarão métodos de consulta adicionais nesse
resultado, conforme mostrado abaixo.
Listagem 9. Utilizando o Gerenciador de Formato Customizado
# Nossa consulta HTML retorna o mesmo número de resultados como o gerenciador
# que filtra explicitamente o conjunto de resultados.
In [1]: Document.html.all().count()
Out[1]: 10
In [2]: Document.get_by_format.html_format().count()
Out[2]: 10
# De fato, podemos provar que eles retornam exatamente os mesmos resultados
In [3]: [d.id for d in Document.get_by_format.html_format()] ==
[d.id for d in Document.html.all()]
Out[3]: True
# Não é mais possível operar na consulta
# não filtrada em HTMLManager()
In [4]: Document.html.filter(format__type='epub')
Out[4]: []
|
Utilize esse método baseado em classe para filtrar consultas quando você espera ter muitas operações em um subconjunto
de seus dados e quer reduzir a quantidade de código e as complexidades das consultas que precisa gerar.
Utilizando Métodos de Classe e Estático com Modelos
Não existem restrições quanto aos tipos de métodos que você pode incluir em um gerenciador. Os métodos podem
retornar QuerySets, conforme mostrado anteriormente, ou podem retornar instâncias da classe
de modelo relacionada (disponível como self.model).
Pode haver casos em que você queira executar operações relacionadas a um modelo, mas não retorna instâncias ou
QuerySets. A documentação do Django declara que todos os métodos que não estão em instâncias de uma classe de modelo
devem ir para o gerenciador, mas outra possibilidade é utilizar os métodos de classe e estático do Python.
Aqui está um exemplo simples de um método utilitário que está relacionado à classe Format,
mas não a uma instância individual:
# Retorne nomes canônicos para uma extensão de formato baseada em alguns
# valores comuns que possam ser vistos "soltos por aí"
def check_extension(extension):
if extension == 'text' or extension == 'txt' or extension == '.csv':
return 'text'
if extension.lower() == 'epub' or extension == 'zip':
return 'epub'
if 'htm' in extension:
return 'html'
raise Exception('Did not get known extension')
|
Esse código não utiliza ou retorna nenhuma instância da classe Format, portanto, ele não
é apropriado como um método de instância. Você poderia incluí-lo em FormatManager, mas como ele
não acessa absolutamente o banco de dados, não parece certo colocá-lo aqui.
Uma solução é incluí-lo na classe Format e declará-lo como um método estático utilizando
o decorador @staticmethod, conforme mostrado abaixo.
Listagem 10. Incluindo uma Função de Utilitário como um Método Estático na Classe de Modelo
class Format(models.Model):
type = models.CharField(choices=( ('Text file', 'text'),
('ePub ebook', 'epub'),
('HTML file', 'html')),
max_length=10)
@staticmethod
def check_extension(extension):
if extension == 'text' or extension == 'txt' or extension == '.csv':
return 'text'
if extension.lower() == 'epub' or extension == 'zip':
return 'epub'
if 'htm' in extension:
return 'html'
raise Exception('Did not get known extension')
def __unicode__(self):
return self.type
|
Esse método seria chamado como Format.check_extension(extension)
sem exigir uma instância de Format ou a criação de um gerenciador.
O Python também oferece o decorador @classmethod, que gera métodos em classes que usam a
classe em si como o primeiro argumento. Isso pode ser útil nos casos em que você queira executar uma certa introspecção no
objeto de classe sem instanciá-lo.
Consultas de Agregação no Django V1.1
Na V1.1, liberada em abril de 2009, o ORM do Django inclui poderosos métodos de consulta que fornecem funcionalidade antes
disponível apenas via SQL bruta. Para desenvolvedores Python desconfiados de SQL — e para qualquer pessoa que
queira manter seus aplicativos Django úteis em vários mecanismos de banco de dados — isso é realmente favorável.
Nos aplicativos de hoje socialmente mediados, é extremamente comum ordenar itens não apenas por campos rígidos, como
por ordem alfabética ou data de criação, mas também por outros tipos de dados dinâmicos. Por exemplo, no aplicativo examples,
talvez você queira listar os documentos por popularidade, baseado no número de comentários feitos sobre cada um.
Antes do Django V1.1, seria necessário fazer isso apenas gravando algum código SQL customizado, criando um procedimento armazenado
não portátil ou — o pior de todos— gravando algumas consultas orientadas a objetos ineficientes. Outra abordagem
era definir um campo do banco de dados simulado que conteria o valor desejado através do qual fazer uma contagem (por exemplo,
o número de linhas de Comentário) e atualizá-lo manualmente através da substituição do método save()
do documento.
A agregação do Django remove a necessidade de se fazer tudo isso. Agora você pode ordenar os documentos pelo número
de comentários que eles recebem com apenas um método QuerySet: annotate(). A
Listagem 11 fornece um exemplo.
Listagem 11. Utilizando Agregação para Ordenar Resultados pelo Número de Comentários
from django.db.models import Count
# Crie alguns Documentos de amostra
unpopular = Document.objects.create(name='Unpopular document', format=format_html)
popular = Document.objects.create(name='Popular document', format=format_html)
# Designe mais comentários para "popular" do que para "não popular"
for i in range(0,10):
Comment.objects.create(document=popular)
for i in range(0,5):
Comment.objects.create(document=unpopular)
# Se retornarmos os resultados na ordem em que eles foram criados (ordem de id, por padrão), obteremos
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- Erro XML: A linha anterior não é maior do que o máximo de 90 caracteres ---------|
# primeiro o documento "não popular".
In [1]: Document.objects.all()
Out[1]: [<Document: Unpopular document>, <Document: Popular document>]
# Se anotarmos o conjunto de resultados com o número total de
# comentários em cada Documento e depois ordenarmos por valor computado,
# obteremos primeiro o documento "popular".
In [2]: Document.objects.annotate(Count('comments')).order_by('-comments__count')
Out[2]: [<Document: Popular document>, <Document: Unpopular document>]
|
O método annotate() QuerySet não executa nenhuma agregação sozinho. Em vez disso, ele
direciona o Django para designar o valor da expressão passada para uma pseudocoluna no conjunto de resultados. Por padrão,
esse nome de coluna será o nome de campo fornecido (aqui, o valor de Comment.document.related_name()) anexado
ao início do nome do método de agregação. Esse código está chamando django.db.models.Count, que
é uma das funções matemáticas simples disponíveis na biblioteca de agregação. (Para obter a lista completa, consulte Recursos.)
O resultado de Document.objects.annotate(Count('comments'))
é um QuerySet ao qual uma nova propriedade — comments__count — foi
incluída. Se quiser substituir esse nome padrão, você pode passar o nome como um argumento de palavra-chave.
Document.objects.annotate(popularity=Count('comments'))
|
Agora que o QuerySet intermediário contém uma contagem de todos os comentários associados
a cada documento, você pode ordenar por esse campo.
Como você quer que os documentos com a maioria dos comentários apareçam primeiro, utilize a ordem decrescente, como .order_by('-comments__count').
O uso de agregação não só reduz a quantidade de código que você precisa gravar, mas também garante que essas operações
serão mais rápidas, já que estão contando com o mecanismo de banco de dados para fazerem os cálculos matemáticos. Esse
processo é muito mais eficiente do que extrair todos os dados relevantes através do ORM e calcular o conjunto de resultados
manualmente.
Outros Tipos de Agregação no Django V1.1
A nova biblioteca de agregação não permite o retorno de conjuntos de resultados mais complexos. Você também pode
retornar resultados não-QuerySet extraídos diretamente do banco de dados. Por exemplo, para
obter o número médio de comentários para todos os documentos no banco de dados, utilize este código:
In [1]: from django.db.models import Avg
In [2]: Document.objects.aggregate(Avg('comments'))
Out[2]: {'comments__avg': 8.0}
|
Você pode aplicar agregação em consultas filtradas ou não filtradas, e as colunas geradas com annotate podem
ser filtradas em campos normais. Também é possível aplicar métodos de agregação em junções. Por exemplo, você poderia
agregar documentos baseados em classificações designadas a comentários, como em um site no estilo "barra e ponto". Para obter informações adicionais sobre agregação, consulte Recursos.
Conclusão
Um encargo no nível dos mapeadores relacionais de objeto é que eles abstraem tanto do mecanismo de banco de dados
que é impossível gravar com eles aplicativos escaláveis e eficientes. Para alguns tipos de aplicativos — aqueles
com milhares de acessos e com modelos altamente inter-relacionados — essa asserção costuma ser verdadeira.
A grande maioria dos aplicativos da Web nunca atinge públicos enormes e não chega a esse nível de complexidade. Entretanto. ORMs
são projetados para serem lançados rapidamente e para ajudarem os desenvolvedores a mergulharem em projetos orientados a bancos de dados
sem exigir profundos conhecimentos em SQL. Conforme seu Web site vai ficando maior e mais popular, você certamente vai precisar fazer uma
auditoria de desempenho, conforme descrito na primeira seção deste artigo. Eventualmente, talvez você precise começar a substituir o
código orientado a ORM por procedimentos armazenados ou SQL bruta.
Felizmente, os recursos de ORMs fáceis de usar como os do Django continuam evoluindo. A biblioteca de agregação do
Django V1.1 é um grande avanço, permitindo uma geração eficiente de consultas, enquanto fornece uma sintaxe orientada a objetos familiar. Para aumentar ainda mais a flexibilidade, os desenvolvedores Python devem consultar SQLAlchemy,
principalmente para aplicativos da Web Python que não contam com o Django.
Recursos Aprender
-
API de Consulta do Django: Consulte
o guia completo para a API de Consulta do Django.
-
Saiba mais sobre o que há de novo no Django V1.1.
-
Consulte a lista completa de todos os mecanismos
de banco de dados que o Django suporta. Desde o Django V1.0, tem sido possível definir novos mecanismos externos também.
-
Visite a biblioteca de agregação do Django V1.1 para
conhecer a referência completa.
-
Para ouvir entrevistas e discussões interessantes para desenvolvedores de software, consulte
podcasts do developerWorks.
-
Mantenha-se atualizado com os eventos Técnicos do developerWorks' e webcasts.
-
Siga developerWorks no Twitter.
-
Consulte novas conferências, exposições, webcasts e outros Eventos em todo o mundo que são extremamente interessantes para desenvolvedores de software livre da IBM.
-
Visite a Zona de software livre do
developerWorks para obter informações sobre instruções extensivas, ferramentas e atualizações de projetos para ajudar você a desenvolver
tecnologias de software livre e a utilizá-las com os produtos da IBM.
-
Assista e aprenda sobre as tecnologias IBM e de software livre e funções de produtos gratuitamente com as Demos On Demand do developerWorks.
Obter produtos e tecnologias
-
Descubra uma alternativa poderosa para o ORM do Django: SQLAlchemy. Esta ferramenta
pode ser a escolha certa para cada grande aplicativo.
-
SQLite V3: Desde a V2.5, o Python é fornecido em um pacote
configurável com suporte para SQLite V3, sem requerer nenhum outro driver.
As versões anteriores do Python requerem que você faça o download do pysqlite diretamente.
-
Inove seu próximo projeto de desenvolvimento de software livre com software de avaliação IBM, disponível para download ou em DVD.
- Faça o download de Versões de avaliação do produto IBM
ou explore as avaliações on-line no
IBM SOA Sandbox e tenha em mãos as ferramentas de desenvolvimento de aplicativos e os produtos de middleware do DB2®, Lotus®
, Rational®, Tivoli® e WebSphere®.
Discutir
Sobre o autor  | 
|  | Liza Daly é uma engenheira de software especializada em aplicativos para o segmento de mercado de publicações. Ela é desenvolvedora líder dos principais produtos on-line da Oxford University Press, O'Reilly Media, e de outros publicadores. Atualmente, ela é uma consultora independente e fundadora da Threepress, um projeto de software livre desenvolvendo aplicativos ebook. |
Avalie esta página
|  |