Sei sulla pagina 1di 12

Usando o MongoDB com Django

Incluindo um banco de dados orientado a documento à combinação

Cesar Otero 08/Mar/2012


Consultant
Freelance Consultant

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.

O Django é usado em um estilo maravilhosamente modular; é simples para substituir os diferentes


componentes de um aplicativo Django baseado na web. Como os bancos de dados NoSQL são mais comuns
nos dias de hoje, pode ser que você queira tentar executar um aplicativo com um backend diferente, em vez
de um dos bancos de dados relacionais padrão, como o MySQL®. Neste artigo, você começa a saborear
o MongoDB, incluindo como chamá-lo em seus projetos Python usando o PyMongo ou o MongoEngine.
Logo, você usa o Django e o MongoEngine para criar um blog simples que pode executar operações Create,
Read, Update, and Delete (CRUD).

Sobre os bancos de dados NoSQL


De acordo com o nosql-database.org, os bancos de dados NoSQL são a "próxima geração de bancos de
dados endereçando primordialmente alguns dos pontos: ser não relacional, distribuído, software livre e
escalável horizontalmente". Nesta classe de banco de dados está o MongoDB, um banco de dados orientado
a documento.

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.

© Copyright IBM Corporation 2012. Todos os direitos reservados. Marcas Registradas


Usando o MongoDB com Django Página 1 de 12
developerWorks® ibm.com/developerWorks/br/

Breve introdução ao MongoDB


O MongoDB age como um interpretador de JavaScript e, portanto, a manipulação do banco de dados é feita
por meio de comandos JavaScript. Depois de instalá-lo localmente na sua máquina (consulte Recursos),
tente alguns dos comandos mostrados em Listagem 1.

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.

Lista 2. Exemplos de criação de documento


var person1 = {name:"John Doe", age:25};
var person2 = {name:"Jane Doe", age:26, dept: 115};

Agora, execute os comandos mostrados na Listagem 3 para criar uma nova coleção.

Lista 3. Criando coleções


db.employees.save(person1);
db.employees.save(person2);

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.

Lista 4. Uma consulta MongoDB simples


> db.employees.find();
// returns
[
{ "_id" : { "$oid" : "4e363c4dcc93747e68055fa1" },
"name" : "John Doe", "age" : 25 },
{ "_id" : { "$oid" : "4e363c53cc93747e68055fa2" },
"name" : "Jane Doe", "dept" : 115, "age" : 26 }
]

Usando o MongoDB com Django Página 2 de 12


ibm.com/developerWorks/br/ developerWorks®

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.

Lista 5. Consulta por um parâmetro de pesquisa


> db.employees.find({name: "John Doe"});
// returns
[
{ "_id" : { "$oid" : "4e363c4dcc93747e68055fa1" },
"name" : "John Doe", "age" : 25 }
]

Para consultar os funcionários com idade acima de 25 anos, execute o comando mostrado na Listagem 6.

Lista 6. Consulta pelos funcionários com idade superior a 25 anos


> db.employees.find({age:{'$gt':25}});
// returns
[
{ "_id" : { "$oid" : "4e363c53cc93747e68055fa2" },
"name" : "Jane Doe", "dept" : 115, "age" : 26 }
]

O $gt é um operador especial que significa maior do que. A Tabela 1 lista alguns outros modificadores.

Tablela 1. Os modificadores que podem ser usados com o MongoDB


Modificador Descrição

$gt Maior que

$lt Menor que

$gte Maior ou igual a

$lte Menor ou igual a

$in Verificar a existência de um array, semelhante ao operador 'in' de SQL.

É possível, evidentemente, atualizar um registro usando o método update() . É possível atualizar todo o
registro, conforme mostrado na Listagem 7.

Lista 7. Atualizar um registro todo


> db.employees.update({
name:"John Doe", // Document to update
{name:"John Doe", age:27} // updated document
});

Como alternativa, é possível atualizar apenas um único valor usando o operador $set , conforme mostrado na
Listagem 8 .

Lista 8. Atualizar um valor único em um registro


> db.employees.update({name:"John Doe",
{ '$set': {age:27} }
});

Usando o MongoDB com Django Página 3 de 12


developerWorks® ibm.com/developerWorks/br/

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.

Lista 9. Remover o "John Doe" da coleção de funcionários


> db.employees.remove({"name":"John Doe"});
> db.employees.find();
// returns
[
{ "_id" : { "$oid" : "4e363c53cc93747e68055fa2" }, "name" : "Jane Doe",
"dept" : 115, "age" : 26 }
]

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.

Integrando o Django ao MongoDB


Você tem algumas opções de acesso ao MongoDB a partir do Python ou Django. A primeira é usar o módulo
Python, PyMongo. Listagem 10 é uma sessão PyMongo de amostra, supondo que você tenha instalado o
MongoDB e já tenha uma instância rodando em uma porta.

Lista 10. Sessão de PyMongo de amostra


from pymongo import Connection

databaseName = "sample_database"
connection = Connection()

db = connection[databaseName]
employees = db['employees']

person1 = { "name" : "John Doe",


"age" : 25, "dept": 101, "languages":["English","German","Japanese"] }

person2 = { "name" : "Jane Doe",


"age" : 27, "languages":["English","Spanish","French"] }

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.

Usando o MongoDB com Django Página 4 de 12


ibm.com/developerWorks/br/ developerWorks®

A semelhança na sintaxe facilita a alternância entre a linha de comando MongoDB e a execução de


comandos com PyMongo. Por exemplo, a Listagem 11 mostra como executar uma consulta com o
PyMongo.

Lista 11. Executar uma consulta com o PyMongo


for e in employees.find({"name":"John Doe"}):
print e

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.

Lista 12. Sessão de exemplo do MongoEngine


from mongoengine import *

connect('employeeDB')

class Employee(Document):
name = StringField(max_length=50)
age = IntField(required=False)

john = Employee(name="John Doe", age=25)


john.save()

jane = Employee(name="Jane Doe", age=27)


jane.save()

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.

Usando o MongoDB com Django Página 5 de 12


developerWorks® ibm.com/developerWorks/br/

Lista 13. Comandos para configuração do projeto de blog Django


$ django-admin.py startproject blongo
$ cd blongo
$ django-admin.py startapp blogapp
$ mkdir templates
$ cd blogapp
$ mkdir static

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.

Lista 15. Código para os arquivos de modelo index.html, update.html e delete.html


<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<link href="{{STATIC_URL}}blog.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Blongo</h1>
<form method="post" action="http://127.0.0.1:8000/">
{% csrf_token %}
<ul>
<li>
<input type="text" name="title" placeholder="Post Title" required>
</li>
<li>
<textarea name="content" placeholder="Enter Content" rows=5 cols=50 required>
</textarea>

Usando o MongoDB com Django Página 6 de 12


ibm.com/developerWorks/br/ developerWorks®

</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>

<!-- update.html -->


<!DOCTYPE html>
<html>
<head>
<link href="{{STATIC_URL}}blog.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Blongo - Update Entry</h1>
<form method="post" action="http://127.0.0.1:8000/update/">
{% csrf_token %}
<ul>
<li><input type="hidden" name="id" value="{{post.id}}"></li>
<li>
<input type="text" name="title" placeholder="Post Title"
value="{{post.title}}" required>
<input type="text" name="last_update"
value="{{post.last_update}}" required>
</li>
<li>
<textarea name="content" placeholder="Enter Content"
rows=5 cols=50 required>
{{post.content}}
</textarea>
</li>
<li>
<input type="submit" value="Save Changes">
</li>
</ul>
</form>
</body>
</html>
<!-- delete.html -->
<!DOCTYPE html>
<html>
<head>
<link href="{{STATIC_URL}}blog.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Blongo - Delete Entry</h1>
<form method="post" action="http://127.0.0.1:8000/delete/">
{% csrf_token %}

Usando o MongoDB com Django Página 7 de 12


developerWorks® ibm.com/developerWorks/br/

<input type="hidden" name="id" value="{{id}}">


<p>Are you sure you want to delete this post?</p>
<input type="submit" value="Delete">
</form>
</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.

Lista 16. Mapeamentos de URL para índice, atualização e exclusão


from django.conf.urls.defaults import patterns, include, url

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 .

Lista 17. Incluindo MongoEngine na camada de dados


from mongoengine import *
from blog.settings import DBNAME

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.

Tablela 2. Tipos de campo MongoEngine e Django ORM equivalentes


Tipo de campo MongoEngine Django ORM equivalente

StringField CharField

URLField URLField

Usando o MongoDB com Django Página 8 de 12


ibm.com/developerWorks/br/ developerWorks®

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.

Lista 18. As visualizações do Django


from django.shortcuts import render_to_response
from django.template import RequestContext
from models import Post
import datetime

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()

# Get all posts from DB


posts = Post.objects
return render_to_response('index.html', {'Posts': posts},
context_instance=RequestContext(request))

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

Usando o MongoDB com Django Página 9 de 12


developerWorks® ibm.com/developerWorks/br/

post.save()
template = 'index.html'
params = {'Posts': Post.objects}

elif request.method == 'GET':


template = 'update.html'
params = {'post':post}

return render_to_response(template, params, context_instance=RequestContext(request))

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 }

return render_to_response(template, params, context_instance=RequestContext(request))

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.

Lista 19. Forma alternativa de recuperar o ID do documento


if request.method == 'POST':
id = request.POST['id']
elif request.method == 'GET':
id = request.GET['id']

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.

Usando o MongoDB com Django Página 10 de 12


ibm.com/developerWorks/br/ developerWorks®

Downloads
Descrição Nome Tamanho
Sample Django application with MongoEngine blongo.zip 12KB

Usando o MongoDB com Django Página 11 de 12


developerWorks® ibm.com/developerWorks/br/

Sobre o autor
Cesar Otero

Cesar Otero é consultor Java e Python freelance. Ele é formado em engenharia elétrica com
especialização em matemática.

© Copyright IBM Corporation 2012. Todos os direitos reservados.


(www.ibm.com/legal/copytrade.shtml)
Marcas Registradas
(www.ibm.com/developerworks/br/ibm/trademarks/)

Usando o MongoDB com Django Página 12 de 12

Potrebbero piacerti anche