Using MongoDB in your Django app
- implications and benefits

By Peter Bengtsson, Fry-IT

About me

  • 10 years RDBMS experience
  • 10 years NoSQL experience (ZODB)
  • 10 years Python experience

But I've never written my own ORM, templating language, web framework or blog engine

Why it matters

Crash course on MongoDB

  • "MongoDB is a scalable, high-performance, open source, document-oriented database. Written in C++"
  • BSON (JSON + datetime)
  • Auto-sharding (July 2010), Master/Slave
  • MapReduce
  • Document-oriented, not key/value
  • Replication Acknowledgement
  • DBRef

Crash course on MongoDB (2)

Compared to...

  • PostgreSQL/MySQL/Oracle etc.
  • CouchDB (slow, JSON)
  • Cassandra (Java)
  • BigTable/Dynamo (Google/Amazon)
  • ZODB (Python pickles)

Bob Ippolito's talk Drop ACID and think about data PyCon 2009

But what does it mean to use MongoDB?

Next step: Implications


  1. No joins
    change the way you browse data

    (note: foreign keys is not the problem)


  1. No joins
  2. Transactions
    change what your views do; to do less


  1. No joins
  2. Transactions
  3. Polymorphism
    inheritance of structure (awesome!)


  1. No joins
  2. Transactions
  3. Polymorphism
  4. Hashed IDs
    e.g. 4bebe6e26b2ded78ec00000a
0123456 7891011
timemachine pidinc


  1. No joins
  2. Transactions
  3. Polymorphism
  4. Hashed IDs
  5. Django Admin
    Haystack, Celery, pagination, flatpages, Piston, etc.
    ...but don't lose hope (Done)

Let's assume we decide to use MongoDB

Next step: Python



(TxMongo - asynchronous variant based on Twisted)

Next step: "ORM"


  • Ming
    SQLAlchemy like
  • MongoKit
    pymongo like
  • MongoEngine
    Django ORM like
  • django-mongodb
    100% transparent, active?
  • django-nonrel
    99% transparent, GSoC

Next step: Django


  • Ming → Ming
  • MongoKit → django-mongokit
  • MongoEngine → MongoEngine

Next step: code


from ming.datastore import DataStore
from ming import Session
from ming import Document, Field, schema

bind = DataStore('mongo://localhost:27017/tutorial')
session = Session(bind)

class WikiPage(Document):

    class __mongometa__:
        session = session
        name = 'wiki_page'

    _id = Field(schema.ObjectId)
    title = Field(str)
    text = Field(str, if_missing='')
    metadata = Field(dict(
>>> for page in WikiPage.m.find()
>>>     print page['title']


from django_mongokit import connection
from django_mongokit.document import DjangoDocument

class WikiPage(DjangoDocument):
    structure = {'title': unicode,
                 'text': unicode,
		 'metadata': {'tags':[unicode],
    required_fields = ['title']
    default_values = {'text': u""}
>>> collection = get_database()['wiki']
>>> for page in collection.WikiPage.find():
>>>     print page.title


from mongoengine import *

class Metadata(EmbeddedDocument):
    tags = ListField(StringField())
    revisions = ListField(IntField())

class WikiPage(Document):
    title = StringField(required=True)
    text = StringField()
    metadata = EmbeddedDocumentField(Metadata)
>>> for page in WikiPage.objects:
>>>     print page.title
So which one should I use?

Next step: why


  1. Least verbose
    pretend you didn't see the import *
  2. Automatic collection management
  3. django-mongoforms
  4. automatic "query inheritance"
  5. Great documentation

But! ...

  1. No signals
    django-mongokit has this
  2. Test database
    again, django-mongokit has this
  3. Maturity?
    applicable to all