Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
O Django, uma estrutura da web do Python, consiste em um sistema de object-relational mapper (ORM),
controlador de backend e modelo. O MongoDB é um banco de dados orientado a documento (também
conhecido como um banco de dados NoSQL) eficaz para ajuste de escala e alto desempenho. Neste
artigo, saiba como chamar o MongoDB a partir do Python (usando MongoEngine) e integrá-lo a um
projeto Django no lugar do ORM integrado. Uma interface da web de amostra é incluída para criar, ler,
escrever e atualizar dados para o backend do MongoDB.
Na prática do dia a dia, o Django 1.3 inclui suporte ao SQLite, MySQL, PostgreSQL e Oracle, mas não
inclui suporte ao MongoDB. No entanto, é fácil incluir suporte ao MongoDB. Infelizmente, a desvantagem é
que você perde o painel de administração automática. Portanto, você tem que pesar isso com relação às suas
necessidades.
Lista 1. Comandos JavaScript de amostra que podem ser testados com o MongoDB
var x = "0";
x === 0;
typeof({});
Não é necessário ser um especialista em JavaScript para começar a usar o MongoDB, ainda assim, seguem
alguns conceitos úteis:
• É possível criar objetos usando a sintaxe literal de objeto, em outras palavras, com duas chaves (por
exemplo var myCollection = {};).
• É possível criar matrizes com colchetes ([]).
• Tudo no JavaScript é um objeto, exceto para números, variáveis booleanas, nulo e indefinido.
Se você quiser saber mais sobre outros recursos do JavaScript, como a programação orientada a objetos de
protótipo (OOP), regras de escopo e a sua natureza de programação funcional, consulte Recursos.
O MongoDB não possui esquemas, contrastando com os bancos de dados relacionais. Em vez de tabelas,
coleções, que consistem em documentos, são usadas. Os documentos são criados usando sintaxe literal de
objeto, conforme mostrado na Listagem 2.
Agora, execute os comandos mostrados na Listagem 3 para criar uma nova coleção.
Como o MongoDB não possui esquemas, person1 e person2 não precisam ter os mesmos tipos de coluna,
ou até o mesmo número de colunas. Além disso, o MongoDB é dinâmico por natureza, por isso cria
funcionários ao invés de lançar um erro. É possível recuperar documentos por meio do método find() . Para
obter todos os documentos em funcionários, chame find() sem qualquer argumento, conforme mostrado na
Listagem 4.
Observe que _id é o equivalente a uma chave primária. Para executar consultas específicas, é necessário
passar outro objeto com o par de chave/valor que indica o que você está consultando, conforme mostrado na
Listagem 5.
Para consultar os funcionários com idade acima de 25 anos, execute o comando mostrado na Listagem 6.
O $gt é um operador especial que significa maior do que. A Tabela 1 lista alguns outros modificadores.
É possível, evidentemente, atualizar um registro usando o método update() . É possível atualizar todo o
registro, conforme mostrado na Listagem 7.
Como alternativa, é possível atualizar apenas um único valor usando o operador $set , conforme mostrado na
Listagem 8 .
Para esvaziar uma coleção, chame o método remove() sem qualquer argumento. Por exemplo, se deseja
remover o "John Doe" da coleção funcionários, você poderia fazer o que é mostrado na Listagem 9.
Isso é apenas o suficiente para você começar. Claro que você pode continuar explorando o site oficial, que
possui um prompt de comando mongodb interativo e puro baseado na web completo com tutorial, bem como
os documentos oficiais. Consulte Recursos.
databaseName = "sample_database"
connection = Connection()
db = connection[databaseName]
employees = db['employees']
print "clearing"
employees.remove()
print "saving"
employees.save(person1)
employees.save(person2)
print "searching"
for e in employees.find():
print e["name"] + " " + unicode(e["languages"])
O PyMongo permite que você execute mais de um banco de dados simultaneamente. Para definir uma
conexão, basta passar em um nome de banco de dados para uma instância de conexão. Os dicionários
Python, neste caso, substituem os literais de objeto JavaScript para criar novas definições de documentos, e
as listas de Python substituem matrizes de JavaScript. O método find retorna um objeto cursor de banco de
dados sobre o qual é possível iterar.
A sua outra opção para chamar o MongoDB a partir do Python é o MongoEngine, que deve ser familiar
caso você já tenha usado o ORM integrado do Django. O MongoEngine é um mapeador de documento
para objeto, que é semelhante, em conceito, a um ORM. Listagem 12 mostra uma sessão de exemplo com o
MongoEngine.
connect('employeeDB')
class Employee(Document):
name = StringField(max_length=50)
age = IntField(required=False)
for e in Employee.objects.all():
print e["id"], e["name"], e["age"]
O objeto Employee recebe herança de mongoengine.Document. Neste exemplo, dois tipos de campo são usados:
StringField e IntField. Assim como o ORM do Django, para consultar todos os documentos na coleção, você
chama o Employee.objects.all(). Observe que para acessar o ID de objeto único, usa-se o "id" em vez de "_id".
Um blog de amostra
Agora, um blog simples chamado Blongo será criado. O Python 1.7, Django 1.3, MongoDB 1.8.2,
MongoEngine 0.4 e Hypertext Markup Language (HTML) 5 serão usados. Se deseja recriar minhas
configurações exatas, eu usei o Ubuntu Linux com o FireFox. O Blongo exibe qualquer entrada de blog
inserida no carregamento da página e permite a atualização e exclusão de qualquer entrada —em outras
palavras, todas as operações CRUD padrão. As visualizações do Django possuem três métodos: index, update
e o delete.
As definições em Cascading Style Sheets (CSS) seguem em um arquivo estático separado. Não entrarei em
detalhes aqui, mas fique à vontade para explorar o código fonte incluso em Download.
Considerando que tudo esteja instalado e funcionando bem, crie um novo projeto Django e os componentes
necessários, conforme mostrado na Listagem 13.
Como novidade para o Django 1.3, há um aplicativo contribuído incluso para uma melhor manipulação de
arquivos estáticos. Ao incluir um diretório estático a qualquer diretório do aplicativo (como blogapp, neste
caso) e certificar-se de que o django.contrib.staticfiles esteja incluído nos aplicativos instalados, o Django
é capaz de localizar arquivos estáticos, como arquivos .css e .js, sem a necessidade de quaisquer ajustes
adicionais. A Listagem 14 mostra as linhas dos arquivos de configuração que foram alteradas (a partir do
arquivo settings.py padrão) para obter o aplicativo de blog em execução.
Lista 14. Linhas dos arquivos de configuração que foram alteradas (a partir do arquivo
settings.py padrão)
# Django settings for blog project.
import os
APP_DIR = os.path.dirname( globals()['__file__'] )
DBNAME = 'blog'
TEMPLATE_DIRS = (
os.path.join( APP_DIR, 'templates' )
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog.blogapp',
)
Você possui três modelos neste projeto: index.html, update.html e delete.html. A Listagem 15 mostra o
código para todos os três arquivos de modelo.
</li>
<li>
<input type="submit" value="Add Post">
</li>
</ul>
</form>
<!-- Cycle through entries -->
{% for post in Posts %}
<h2> {{ post.title }} </h2>
<p>{{ post.last_update }}</p>
<p>{{ post.content }}</p>
<form method="get" action="http://127.0.0.1:8000/update">
<input type="hidden" name="id" value="{{ post.id }}">
<input type="hidden" name="title" value="{{ post.title }}">
<input type="hidden" name="last_update" value="{{ post.last_update }}">
<input type="hidden" name="content" value="{{ post.content }}">
<input type="submit" name="" value="update">
</form>
<form method="get" action="http://127.0.0.1:8000/delete">
<input type="hidden" name="id" value="{{post.id}}">
<input type="submit" value="delete">
</form>
{% endfor %}
</body>
</html>
Em seguida, altere os mapeamentos de URL para o código mostrado na Listagem 16, que aponta para
as visualizações para o índice, atualização e exclusão. Se você deseja que o blog de amostra crie novas
entradas de blog (no índice), atualize as postagens de blog existentes e as exclua quando desejar. Cada ação
é realizada pela postagem para uma URL específica.
urlpatterns = patterns('',
url(r'^$', 'blog.blogapp.views.index'),
url(r'^update/', 'blog.blogapp.views.update'),
url(r'^delete/', 'blog.blogapp.views.delete'),
)
Observe que não é necessário executar o comando syncdb do Django. Para integrar o MongoDB ao seu
aplicativo, é necessário o MongoEngine. No arquivo models.py do diretório blogapp, inclua o código
mostrado na Listagem 17 .
connect(DBNAME)
class Post(Document):
title = StringField(max_length=120, required=True)
content = StringField(max_length=500, required=True)
last_update = DateTimeField(required=True)
O nome do banco de dados é obtido a partir do arquivo de definições para separar os interesses. Cada
postagem do Blog contém três campos obrigatórios: title, content e o last_update. Se você comparar e contrastar
esta listagem com o que você faria normalmente no Django, a diferença não será enorme. Em vez de ter
uma classe que herda do django.db.models.Model, esta listagem usa a classe mongoengine.Document em seu
lugar. A diferença entre os tipos de dados não será detalhada aqui, mas sinta-se a vontade para verificar os
documentos do MongoEngine (consulte Recursos).
Tabela 2 lista os tipos de campo MongoEngine e mostra o tipo de campo Django ORM equivalente, se
houver.
StringField CharField
URLField URLField
EmailField EmailField
IntField IntegerField
FloatField FloatField
DecimalField DecimalField
BooleanField BooleanField
DateTimeField DateTimeField
EmbeddedDocumentField Nenhum
DictField Nenhum
ListField Nenhum
SortedListField Nenhum
BinaryField Nenhum
ObjectIdField Nenhum
FileField FileField
Finalmente, é possível configurar as suas visualizações. Seguem três métodos de visualização: index, update
e o delete. Para executar a ação desejada, deve ser feita uma solicitação de postagem para a URL específica.
Por exemplo, para atualizar um documento deve ser feita uma postagem para localhost:8000/update.
Executar uma solicitação http 'GET' não salvará, atualizará e assim por diante. As novas postagens do blog
são inseridas a partir da visualização de índice. Listagem 18 mostra as implementações para as visualizações
de índice, atualização e exclusão.
def index(request):
if request.method == 'POST':
# save new post
title = request.POST['title']
content = request.POST['content']
post = Post(title=title)
post.last_update = datetime.datetime.now()
post.content = content
post.save()
def update(request):
id = eval("request." + request.method + "['id']")
post = Post.objects(id=id)[0]
if request.method == 'POST':
# update field values and save to mongo
post.title = request.POST['title']
post.last_update = datetime.datetime.now()
post.content = request.POST['content']
post.save()
template = 'index.html'
params = {'Posts': Post.objects}
def delete(request):
id = eval("request." + request.method + "['id']")
if request.method == 'POST':
post = Post.objects(id=id)[0]
post.delete()
template = 'index.html'
params = {'Posts': Post.objects}
elif request.method == 'GET':
template = 'delete.html'
params = { 'id': id }
Você deve ter notado as instruções eval usadas para recuperar os IDs do documento. Isso é usado para evitar
a necessidade de gravar a instrução if mostrada na Listagem 19.
Também é possível escrever dessa maneira. Isso é tudo o que preciso para ter um blog simples ativo e
funcionando. Obviamente, faltam muitos componentes para um produto final, tais como usuários, um login,
tags e assim por diante.
Conclusão
Como você pode ver, não há realmente muito para chamar o MongoDB a partir do Django. Neste artigo,
apresentei rapidamente o MongoDB e expliquei como acessá-lo e manipular suas coleções e documentos
a partir do Python por meio do wrapper PyMongo e o mapeador de objeto para documento MongoEngine.
Finalmente, ofereci uma rápida demonstração de como criar um formulário CRUD básico usando o Django.
Embora esta seja apenas a primeira etapa, espero que você entenda agora como aplicar esta configuração em
seus próprios projetos.
Downloads
Descrição Nome Tamanho
Sample Django application with MongoEngine blongo.zip 12KB
Sobre o autor
Cesar Otero
Cesar Otero é consultor Java e Python freelance. Ele é formado em engenharia elétrica com
especialização em matemática.