Clone wiki

doqu / Home




Models is a lightweight framework for mapping Python classes to schema-less databases. It is not an ORM as it doesn't map existing schemata to Python objects but instead defines them on a higher layer built upon a schema-less storage (key/value or document-oriented). You define models as a valuable subset of the whole database and work with only certain parts of existing entities -- the parts you need.

Project status

I'm aiming to make Models work primarily with Pyrant as a backend and Datashaping as a higher-level query tool. In the future SQL backends may be used, but I don't believe this is a valuable niche for Models, as there are already excellent ORMs.

Quick example

Not surprising to those who had ever used an ORM:

class Country(Model):
    name = Property()

    def __unicode__(self):

    class Meta:
        must_have = {'type': 'country'}

class Person(Model):
    first_name = Property(required=True)
    last_name = Property(required=True)
    gender = Property()
    birth_date = Date()
    birth_place = Reference(Country)

    def __unicode__(self):
        return self.full_name    # full_name is a dynamic attribute, see below

    def age(self):
        return ( - self.birth_date).days / 365

    def full_name(self):
        return '%s %s' % (self.first_name, self.last_name)

    class Meta:
        must_have = {'type': 'person'}

The interesting part is the Meta subclass. It contains a must_have attribute which actually binds the model to a subset of data in the storage. {'type':'person'} states that a data row/document/... must contain a type field with value person. You can easily define any other query conditions. If you create an empty Person instance, it will have all the "must haves" pre-filled.

Now let's try these models with a Tokyo Tyrant database using Pyrant:

>>> from pyrant import Tyrant
>>> storage = Tyrant()
>>> guido = Person.query(storage).filter(first_name='Guido')[0]
>>> guido
<Person Guido van Rossum>
>>> guido.first_name
>>> guido.birth_date, 1, 31)
>>> guido.age
>>> guido.birth_place = Country(name="Netherlands")
>>> guido.birth_place
<Country Netherlands>

...and so on.

And, yes, it already works with Tokyo Tyrant -- the database manager for the hyper-fast Tokyo Cabinet. Note that relations are supported out of the box.