Package: micromongo
micromongo is a tiny layer around pymongo that allows you to create simple
ORM-style classes that can perform validation, allow dot access to documents,
auto-wrap queryset results, and give you pre/post save hooks.It’s designed with microframeworks in mind, but is application and framework
agnostic.  It is meant to simplify usage of pymongo and provide tools for
common idioms, not to obscure pymongo or mongodb from your data structures.You are welcome to open issues or send pull requests onmicromongo’s githubmicromongomakes a few design decisions in the name of simplification that
might not work for you:micromongo maintains a single global connection, so you cannot have models
that connect to multiple mongodb serversthere are a handfull of model names and document attribute names that will
not work with micromongo models;  these will be covered in thefull docsyou can only have one model per collectiongetting startedTo start off with micromongo, just import it:>>> from micromongo import connect, Model
>>> c = connect()connecttakes the same arguments aspymongo’s Connectionobject, and
behaves almost identically, except that it attempts to automatically return
query results wrapped in the appropriate Model classes.  The connection object
that you create via this call will be cached and used by the various ORM-style
facilities, likeModel.save(),Model.proxy, etc.  If you want a clean,
standardConnectionobject, you can get one easily:>>> from micromongo import clean_connection
>>> clean = clean_connection()Note that clean_connection does not take arguments and will always return a
cleanConnectionclass with the same settings as the current micromongo
connection.With these connection objects, you can create databases or do whatever you
would with normalpymongoobjects:>>> db = c.test_db
>>> collection = db.test_collection
>>> collection.save({"docid": 1, "fail": False})
>>> collection.find_one()
{u'_id': ObjectId('...'), u'fail': False, u'docid': 1}You can also declare your own Model for a particular collection in
declarative style:>>> class TestModel(Model):
        collection = 'test_db.test_collection'

>>> collection.find_one()
<TestModel: {u'_id': ObjectId('...'), u'fail': False, u'docid': 1}>These classes have a number of additional features over a dictionary that can
make them much more convenient to use.  The document keys are all accessible
as attributes:>>> t = collection.find_one()
>>> t.fail
False
>>> t.docid
1The documents are also easily persisted to the database:>>> t.docid = 17
>>> t.save()
>>> clean.test_db.test_collection.find_one()
{u'_id': ObjectId('...'), u'fail': False, u'docid': 17}defining modelsAbove, thecollectionattribute was assigned to ourFoomodel.  This
was a shortcut, though;  ifdatabaseandcollectionare assigned
separately, the Model can figure out the full collection name.  If the
collection and database are not present, micromongo attempts to figure it out
based on the class and module name of your Model.  For instance,blog.Postwill becomeblog.post, orstream.StreamEntrywill becomestream.stream_entry.  Explicit is better than implicit, and it’s encouraged
that you set the collection manually.Besides packing and unpacking results from the database, models can also define
aspecdocument which can define defaults and perform validation before
saving the model.  Take a trivial blog post model:>>> from micromongo.spec import *
>>> class Post(Model):
        collection = 'test_db.blog_posts'
        spec = dict(
            author=Field(required=True, default='jmoiron', type=basestring),
            title=Field(required=False, default='', type=basestring),
            published=Field(required=True, default=False, type=[True, False]),
            body=Field(type=unicode),
            timestamp=Field(),
        )

>>> p = Post.new()
>>> p
<Post: {'title': u'', 'author': u'jmoiron', 'published': False}>A few things are going on here.  Fields that have a default are initialized to
that default whether they are required or not.  If a required field does not
have a default, it’s initialized toNone.Fields can take atypeargument, which can either be a callable that takes
a value and returns True or False, one or more base types, or one or more
values.  If one or more types are provided,isinstanceis used to test that
values are the right type.  If one or more values are provided, the Field acts
as an enum type, checking that values are in its set of values.  If no type is
given, validation always passes on a fieldunlessit is required and absent.If a field in p is given an invalid type, then aValueErroris raised:>>> p.title = 10
>>> p.save()
Traceback (most recent call last):
  ...
ValueError: Keys did not match spec: ['title']
>>> del p.author
>>> p.save()
Traceback (most recent call last):
  ...
ValueError: Missing fields: ['author'], Invalid fields: ['title']
>>> p.title = 'My first blogpost'
>>> p.author = 'jmoiron'
>>> p.published = True
>>> p.body = u"This is my first blog post..  I'm so excited!"
>>> p.save()Model.findFor convenience and DRY,Model.findis a classmethod that will use
micromongo’s cursor to issue a find against the right collection.  This method
behaves exactly the same aspymongo’s Collection.find.micromongo’s slightly modifiedCursorclass also makes a django-inspiredorder_bymethod available to all cursors (findand anything you chain
off if it returns a cursor).  You can pass one or more field names, with an
optional leading ‘-’, to sort things by ascending or descending order.These changes allow you to use most of the power of pymongo without having to
import it, and lets you avoid needless repetition of the location of your data.field subclassingYou are encouraged to create your own Fields that do what you want.  Field
subclasses have a hook functionpre_validatewhich take an incoming value
and can transform it however they want.  Note that this will only work if the
fields are actually present; so to get something like anauto_now_addon aDateTimeField, you will want to make it required and have itspre_validateturnNoneintodatetime.datetime.now().