Tabla de Contenidos

MongoEngine

It's a MongoDB ORM for Python.

First steps

Installation and import

$ pip install mongoengine

To start using MongoEngine we will import like this:

import mongoengine

Connecting to a DB

To connect a DB we will use the connect function, its first argument is the DB:

connect('project1')
connect('project1', host='192.168.1.35', port=12345)
connect('project1', username='webapp', password='pwd123')
connect('project1', host='mongodb://localhost/database_name')

Defining the schema

In a nutshell

Next schema implements a Blog where a User can create different type Posts. Those types are inherited classes from Post.

class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)
 
class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
    meta = {'allow_inheritance': True}
 
class TextPost(Post):
    content = StringField()
 
class ImagePost(Post):
    image_path = StringField()
 
class LinkPost(Post):
    link_url = StringField()

Other field objects

More about this subject in: http://docs.mongoengine.org/guide/defining-documents.html#fields

Storing an object

Comment.objects.create(text='Me gusta!')

Storing an object inside another

class Comment(EmbeddedDocument):
    content = StringField()
    name = StringField(max_length=120)
 
class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
    tags = ListField(StringField(max_length=30))
    comments = ListField(EmbeddedDocumentField(Comment))

We also could use GenericReferenceField to reference any kind of document:

class Bookmark(Document):
    bookmark_object = GenericReferenceField()

Cascade delete

When we define a ReferenceField we can indicate reverse_delete_rule=CASCADE to delete all the objects when a referenced object is deleted (it does not work with MapFields neither DictFields).

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User, reverse_delete_rule=CASCADE)
    tags = ListField(StringField(max_length=30))
    comments = ListField(EmbeddedDocumentField(Comment))

Other constans we can pass:

Dynamic documents

DynamicDocument documents work like Document but any data or attributes set to them will also be saved (fields cannot start with _ ).

from mongoengine import *

class Page(DynamicDocument):
    title = StringField(max_length=200, required=True)

# Create a new page and add tags
page = Page(title='Using MongoEngine')
page.tags = ['mongodb', 'mongoengine']
page.save()

Defining constraints

We can specify field uniqueness with unique=True and multi-fielduniqueness with unique_with (for a field name, or a list, or a tuple):

class User(Document):
    username = StringField(unique=True)
    first_name = StringField()
    last_name = StringField(unique_with='first_name')

Editing Data

Adding documents

ross = User(email='ross@example.com', first_name='Ross', last_name='Lawley').save()
 
# this is other way to save ross 
ross1 = User(email='ross1@example.com')
ross1.first_name = 'Ross1'
ross1.last_name = 'Lawley'
ross1.save()
 
post1 = TextPost(title='Fun with MongoEngine', author=john)
post1.content = 'Took a look at MongoEngine today, looks pretty cool.'
post1.tags = ['mongodb', 'mongoengine']
post1.save()
 
post2 = LinkPost(title='MongoEngine Documentation', author=ross)
post2.link_url = 'http://docs.mongoengine.com/'
post2.tags = ['mongoengine']
post2.save()

Accessing data

A Document object is actually a QuerySet object. It lazily queries the database when you need the data. QuerySet objects perform searches on the data base using functions like…

Examples

Retrieving all the post titles

for post in Post.objects:
    print post.title

Retrieving a concrete type content

for post in TextPost.objects:
    print post.content

Searching by tag

for post in Post.objects(tags='mongodb'):
    print post.title

Others

Django support

Connecting

You only need to call connect() somewhere in the settings module.

If you were not using another Database backend you may need to add a dummy database:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.dummy'
    }
}

Users

Django authentication classes are included as Document classes so they are compatible. To enable them you should add the following to your settings.py file:

AUTHENTICATION_BACKENDS = (
    'mongoengine.django.auth.MongoEngineBackend',
)

Remember to call set_password() method in User class when assign a password value:

instance.set_password(attrs.get('password', instance.password))