mercilessming

A minimalistic python dict model for mongodb


License
MIT
Install
pip install mercilessming==0.0.8

Documentation

mercilessming

Ming the Merciless is the ultimate evil ruler of the Mongo planet in the Flash Gordon comic strip. But it's also a minimalistic python dict model for mongodb.

Getting Started

After downloading and installing the package, you'll first need to configure it to work against a specific Pymongo Database instance:

import mercilessming
import pymongo

db = pymongo.MongoClient( ... )[ "my_db" ]
mercilessming.Model.connect( db )

mercilessming.Model is the base class representing a MongoDB collection. Instances of this class (or subclasses) represent MongoDB documents (records):

doc = mercilessming.Model( "some_id" )
doc[ "name" ] = "Ming"
doc[ "occupation" ] = "Villan"
doc.save()

The code snippet above will upsert the document with id some_id and the values { "name": "Ming", "occupation": "Villan" } to the mercilessming.Model collection.

Note that the mercilessming.Model class inherits from Python's native dict class. This allows handling Model instances as normal dicts in addition to the extended functionality provided by mercilessming like .save() or .load()

Subclasses

In the example above, all instances of mercilessming.Model will be written to the same model under the same name. In order to separate your data and models in a more organized way, you'll want to subclass the mercilessming.Model class:

class Villan( mercilessming.Model ):
    pass

ming = Villan( { "hometown": "Mingo City" } )
ming.save()

The document above will be saved, by default, to the modulename.Villan collection. You can change this default behavior by overriding the .collection() method that should return a valid Pymongo collection instance.

Note The Model constructor can receive either a document-id, and act as a normal Python dict constructor that can receive named arguments, another dict, iterator, etc.. If no id is defined, this document will be assigned an id by MongoDB automatically upon save.

Default values

It's possible to assign default values to the Model dictionary by using the Model.defaults attribute:

class Villan( mercilessming.Model ):
    defaults = {
        "type": "villan"
    }

ming = Villan( "ming" )
print ming[ "type" ] # prints 'villan'
ming.save() # saves { "type": "villan", "_id": "ming" }

This code snippet will save the document: { "type": "villan", "_id": "ming" }

Note The defaults attribute doesn't inherit from the parent Model.

Model Linking

If your Model holds references to other mercilessming.Model instances it will be encoded with a special __link attribute when saved. This allows mercilessming to re-create the linked Model upon .load():

...
ming = Villan( "ming" ).save()
mercilessming.Model( "gordon", nemesis = ming ).save()
gordon = mercilessming.Model( "gordon" ).load()
print gordon[ "nemesis" ] == Villan( "ming" )

The last line will print True because the gordon Model will now refernece the Villan instance.

Note Calling .load() on a Model that has a linked refernece to a different Model causes mercilessming to attempt to instantiate the linked Model using its full class path (i.e. "module.ClassName(id)"). If the class path does not exist (not imported elsewhere, or renamed/removed) the .load() command will throw a NameError (for missing module) or AttributeError (for missing ClassName).

Lazy Loading

You can configure your Models to load lazily whenever there is an attempt to read, write or delete one of its items by turning on the .lazy flag:

class LazyVillan( Model ):
    lazy = True

LazyVillan( "ming", occupation = "villan" ).save()
m = LazyVillan( "ming" ) # m._loaded == False
print LazyVillan( "ming" )[ "occupation" ] # prints 'villan', m._loaded == True

The lazy loading mechanism is triggered by the Model's .__setitem__(), .__getitem__(), .__delitem__(), .get() and .update() methods.