Modeling

MotorEngine uses the concept of models to interact with MongoDB. To create a model we inherit from the Document class:

class motorengine.document.Document(_is_partly_loaded=False, _reference_loaded_fields=None, **kw)

Base class for all documents specified in MotorEngine.

Let’s say we need an article model with title, description and published_date:

from motorengine.document import Document
from motorengine.fields import StringField, DateTimeField

class Article(Document):
    title = StringField(required=True)
    description = StringField(required=True)
    published_date = DateTimeField(auto_now_on_insert=True)

That allows us to create, update, query and remove articles with extreme ease:

new_title = "Better Title %s" % uuid4()

def create_article():
    Article.objects.create(
        title="Some Article",
        description="This is an article that really matters.",
        callback=handle_article_created
    )

def handle_article_created(article):
    article.title = new_title
    article.save(callback=handle_article_updated)

def handle_article_updated(article):
    Article.objects.filter(title=new_title).find_all(callback=handle_articles_loaded)

def handle_articles_loaded(articles):
    assert len(articles) == 1
    assert articles[0].title == new_title

    articles[0].delete(callback=handle_article_deleted)

def handle_article_deleted(number_of_deleted_items):
    try:
        assert number_of_deleted_items == 1
    finally:
        io_loop.stop()

io_loop.add_timeout(1, create_article)
io_loop.start()

Base Field

class motorengine.fields.base_field.BaseField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

This class is the base to all fields. This is not supposed to be used directly in documents.

Available arguments:

  • db_field - The name this field will have when sent to MongoDB
  • default - The default value (or callable) that will be used when first creating an instance that has no value set for the field
  • required - Indicates that if the field value evaluates to empty (using the is_empty method) a validation error is raised
  • on_save - A function of the form lambda doc, creating that is called right before sending the document to the DB.
  • unique - Indicates whether an unique index should be created for this field.
  • sparse - Indicates whether a sparse index should be created for this field. This also will not pass empty values to DB.

To create a new field, four methods can be overwritten:

  • is_empty - Indicates that the field is empty (the default is comparing the value to None);
  • validate - Returns if the specified value for the field is valid;
  • to_son - Converts the value to the BSON representation required by motor;
  • from_son - Parses the value from the BSON representation returned from motor.

Available Fields

class motorengine.fields.string_field.StringField(max_length=None, *args, **kw)

Field responsible for storing text.

Usage:

name = StringField(required=True, max_length=255)

Available arguments (apart from those in BaseField):

  • max_length - Raises a validation error if the string being stored exceeds the number of characters specified by this parameter
class motorengine.fields.datetime_field.DateTimeField(auto_now_on_insert=False, auto_now_on_update=False, tz=None, *args, **kw)

Field responsible for storing dates.

Usage:

date = DateTimeField(required=True, auto_now_on_insert=True, auto_now_on_update=True)

Available arguments (apart from those in BaseField):

  • auto_now_on_insert - When an instance is created sets the field to datetime.now()
  • auto_now_on_update - Whenever the instance is saved the field value gets updated to datetime.now()
  • tz - Defines the timezone used for auto_now_on_insert and auto_now_on_update and should be enforced on all
    values of this datetime field. To interpret all times as UTC use tz=datetime.timezone.utc (Defaults: to None, which means waht you put in comes out again)
class motorengine.fields.uuid_field.UUIDField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

Field responsible for storing uuid.UUID.

Usage:

name = UUIDField(required=True)
class motorengine.fields.url_field.URLField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

Field responsible for storing URLs.

Usage:

name = URLField(required=True)

Available arguments (apart from those in BaseField): None

Note

MotorEngine does not implement the verify_exists parameter as MongoEngine due to async http requiring the current io_loop.

class motorengine.fields.email_field.EmailField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

Field responsible for storing e-mail addresses.

Usage:

name = EmailField(required=True)

Available arguments (apart from those in BaseField): None

class motorengine.fields.int_field.IntField(min_value=None, max_value=None, *args, **kw)

Field responsible for storing integer values (int()).

Usage:

name = IntField(required=True, min_value=0, max_value=255)

Available arguments (apart from those in BaseField):

  • min_value - Raises a validation error if the integer being stored is lesser than this value
  • max_value - Raises a validation error if the integer being stored is greather than this value
class motorengine.fields.boolean_field.BooleanField(*args, **kw)

Field responsible for storing boolean values (bool()).

Usage:

isActive = BooleanField(required=True)

BooleanField has no additional arguments available (apart from those in BaseField).

class motorengine.fields.float_field.FloatField(min_value=None, max_value=None, *args, **kw)

Field responsible for storing floating-point values (float()).

Usage:

name = FloatField(required=True, min_value=0.1, max_value=255.6)

Available arguments (apart from those in BaseField):

  • min_value - Raises a validation error if the float being stored is lesser than this value
  • max_value - Raises a validation error if the float being stored is greather than this value
class motorengine.fields.decimal_field.DecimalField(min_value=None, max_value=None, precision=2, rounding='ROUND_HALF_UP', *args, **kw)

Field responsible for storing fixed-point decimal numbers (decimal.Decimal).

Usage:

import decimal

name = DecimalField(required=True, min_value=None, max_value=None, precision=2, rounding=decimal.ROUND_HALF_UP)

Available arguments (apart from those in BaseField):

  • min_value - Raises a validation error if the decimal being stored is lesser than this value

  • max_value - Raises a validation error if the decimal being stored is greather than this value

  • precision - Number of decimal places to store.

  • rounding - The rounding rule from the python decimal library:

    • decimal.ROUND_CEILING (towards Infinity)
    • decimal.ROUND_DOWN (towards zero)
    • decimal.ROUND_FLOOR (towards -Infinity)
    • decimal.ROUND_HALF_DOWN (to nearest with ties going towards zero)
    • decimal.ROUND_HALF_EVEN (to nearest with ties going to nearest even integer)
    • decimal.ROUND_HALF_UP (to nearest with ties going away from zero)
    • decimal.ROUND_UP (away from zero)
    • decimal.ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

Note

Decimal field stores the value as a string in MongoDB to preserve the precision.

class motorengine.fields.binary_field.BinaryField(max_bytes=None, *args, **kwargs)

Field responsible for storing binary values.

Usage:

name = BinaryField(required=True)

Available arguments (apart from those in BaseField):

  • max_bytes - The maximum number of bytes that can be stored in this field
class motorengine.fields.json_field.JsonField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

Field responsible for storing json objects.

Usage:

name = JsonField(required=True)

Available arguments (apart from those in BaseField): None

Note

If ujson is available, MotorEngine will try to use it. Otherwise it will fallback to the json serializer that comes with python.

class motorengine.fields.objectid_field.ObjectIdField(db_field=None, default=None, required=False, on_save=None, unique=None, sparse=False)

Field responsible for storing object ids.

Usage:

objectid = ObjectIdField(required=True)

Multiple Value Fields

class motorengine.fields.list_field.ListField(base_field=None, *args, **kw)

Field responsible for storing list.

Usage:

posts = ListField(StringField())

Available arguments (apart from those in BaseField):

  • base_field - ListField must be another field that describe the items in this list

Embedding vs Referencing

Embedding is very useful to improve the retrieval of data from MongoDB. When you have sub-documents that will always be used when retrieving a document (i.e.: comments in a post), it’s useful to have them be embedded in the parent document.

On the other hand, if you need a connection to the current document that won’t be used in the main use cases for that document, it’s a good practice to use a Reference Field. MotorEngine will only load the referenced field if you explicitly ask it to, or if you set __lazy__ to False.

class motorengine.fields.embedded_document_field.EmbeddedDocumentField(embedded_document_type=None, *args, **kw)

Field responsible for storing an embedded document.

Usage:

class Comment(Document):
    text = StringField(required=True)

comment = EmbeddedDocumentField(embedded_document_type=Comment)

Available arguments (apart from those in BaseField):

  • embedded_document_type - The type of document that this field accepts as an embedded document.
class motorengine.fields.reference_field.ReferenceField(reference_document_type=None, *args, **kw)

Field responsible for creating a reference to another document.

Usage:

class User(Document):
    name = StringField(required=True)
    email = EmailField(required=True)

owner = ReferenceField(reference_document_type=User)

Available arguments (apart from those in BaseField):

  • reference_document_type - The type of document that this field accepts as a referenced document.