as your primary
Django database

By Andre Medeiros at DjangoCon Finland 2013


Andre Medeiros

Founder at
Next generation discussion forums


Brazilian that doesn't play soccer

M.Sc. from Aalto University

MongoDB logo

It's just a JSON datastore

fooman = {"name" : "Foo", "age" : 25};;

MongoDB is
Agile and Scalable

  • Dynamic schemas
  • Index on any attribute
  • Auto-sharding

→ Popular NoSQL database

Logos of Foursquare, Forbes, Flowdock, IGN, Intuit, Sourceforge, and Trello

Why MongoDB for Django?

The “pythonic database”

dict ~ JSON

# Python
person = {
	'name': "John Doe", 
	'skills': ["Javascript", "CSS", "HTML"],
	'work': None

// Javascript
person = {
	"name" : "John Doe", 
	"skills" : ["Javascript", "CSS", "HTML"],
	"work" : null
Writing Python is fun, and keeping everything in Python limits the number of times your brain has to do a "context switch." It helps productivity if you keep yourself in a single programming environment/mentality for as long as possible.
MongoDB is meant for rapid and agile web development
(say bye to migrations)

If MongoDB had existed 10 years ago the vast majority of data used to drive modern web applications would be stored in MongoDB and not a relational database.
—Will Shulman, CEO & Co-founder of MongoLab

Real world example

Comments and tags
embedded into discussion document

	"_id" : ObjectId("5500165de50c050005e4b29f"),
	"title" : "Using MongoDB as your primary Django database",
	"message" : "This presentation introduces MongoDB to Django de...",
	"author" : ObjectId("5182953ba50c051575e4b29c"),
	"creation_date" : ISODate("2013-05-21T12:44:31.408Z"),
	"tags" : ["django","python","mongodb","mongoengine","nosql"],
	"comments" : [
			"author" :  ObjectId("50c90b3128650a004200961a"),
			"message" : "Nice, I didn't know this was possible."

with MongoDB

At the core of Django is its ORM

is an Object-Document Mapper made for MongoDB, following Django's ORM style.

pip install mongoengine==0.8.0

MongoEngine model


from mongoengine import *

class Choice(EmbeddedDocument):
    choice_text = StringField(max_length=200)
    votes = IntField(default=0)

class Poll(Document):
    question = StringField(max_length=200)
    pub_date = DateTimeField(help_text='date published')
    choices = ListField(EmbeddedDocumentField(Choice))

Translated to MongoDB...

	"_id" : ObjectId("5483165de50c050005e4b29f"),
	"question" : "What's up?",
	"pub_date" :  ISODate("2013-04-14T11:06:21.922Z"),
	"choices" : [
			"choice_text" : "Not much",
			"votes" : 0
			"choice_text" : "Just hacking again",
			"votes" : 1

Querying and updating


from yourproject.models import Poll, Choice

poll = Poll.objects(question__contains="What").first()
choice = Choice(choice_text="I'm at", votes=23)

print poll.question

Setting indexes


class Poll(Document):
	question = StringField(max_length=200)
	pub_date = DateTimeField(help_text='date published')
	choices = ListField(EmbeddedDocumentField(Choice))

	meta = {
		'indexes': [
			('pub_date', '+question')

The fun side

No python syncdb
No database migrations
Freedom to hack

The painful side

Making Django ignore its
relational database components

Django, forget your databases


import mongoengine

	'default': {
		'ENGINE': '',

SESSION_ENGINE = 'mongoengine.django.sessions' # optional

Connect to MongoDB


_MONGODB_USER = 'mongouser'
_MONGODB_PASSWD = 'password'
_MONGODB_HOST = 'thehost'
_MONGODB_NAME = 'thedb'
	'mongodb://%s:%s@%s/%s' \

mongoengine.connect(_MONGODB_NAME, host=_MONGODB_DATABASE_HOST)

Use MongoEngine's User




import mongoengine

# ...

user = authenticate(username=username, password=password)
assert isinstance(user, mongoengine.django.auth.User)

Hack the test runner


from django.test.simple import DjangoTestSuiteRunner
from django.test import TestCase

class NoSQLTestRunner(DjangoTestSuiteRunner):
	def setup_databases(self):
	def teardown_databases(self, *args):

class NoSQLTestCase(TestCase):
	def _fixture_setup(self):
	def _fixture_teardown(self):


TEST_RUNNER = 'yourproject.tests.NoSQLTestRunner'

Or use Mongorunner

MongoEngine is good

  • Maintained and updated constantly by 10gen
  • Solid and works like Django's ORM
  • A replaceable component in Django

Alternative to MongoEngine

Forked from Django 1.3
Supports MongoDB and Google App Engine

When NOT to use MongoDB

  • You need ACID transactions
  • You have a stable SQL database in production
  • You need the most stable RDBMS you can get

Consider MongoDB when...

  • You are starting a project with design freedom
  • Your app has an evolving data schema
  • Your want auto-sharding on a simple schema
  • Your app has plenty of geospatial data
  • You have high-volume traffic
  • Your app works around a RESTful JSON API

Thank you