Need help with remodel?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

196 Stars 27 Forks MIT License 145 Commits 2 Opened issues


Very simple yet powerful and extensible Object Document Mapper for RethinkDB, written in Python.

Services available


Need anything else?

Contributors list


Build Status

Very simple yet powerful and extensible Object Document Mapper for RethinkDB, written in Python.

It is plain simple!

from remodel.models import Model

class User(Model): pass

That's really everything you need to do to set up a model!

Don't forget to turn on your RethinkDB server and to create your tables (check the examples below for a helper that does just that!).


  • schemaless;
  • dict
  • full support for relations;
  • indexes;
  • convention over configuration;
  • lazy-loading;
  • caching;
  • thoroughly tested;


pip install remodel


Basic CRUD operations

class Order(Model):


my_order = Order.create(customer='Andrei', shop='GitHub')


my_order['total'] = 100


saved_order = Order.get(customer='Andrei')



Creating tables

from remodel.models import Model
from remodel.helpers import create_tables, create_indexes

class Party(Model): has_many = ('Guest',)

class Guest(Model): belongs_to = ('Party',)

Creates all database tables defined by models


Creates all table indexes based on model relations


Configuring database connection

Setups are widely different, so here's how you need to configure remodel in order to connect to your RethinkDB database:

from remodel.connection import pool

pool.configure(host='localhost', port=28015, auth_key=None, user='admin', password='', db='test')


Has one / Belongs to

class User(Model):
    has_one = ('Profile',)

class Profile(Model): belongs_to = ('User',)

andrei = User.create(name='Andrei') profile = Profile.create(user=andrei, network='GitHub', username='linkyndy') print profile['user']['name'] # prints Andrei

Has many / Belongs to

class Country(Model):
    has_many = ('City',)

class City(Model): belongs_to = ('Country',)

romania = Country.create(name='Romania') romania['cities'].add(City(name='Timisoara'), City(name='Bucharest')) print romania['cities'].count() # prints 2

Has and belongs to many

class Post(Model):
    has_and_belongs_to_many = ('Tag',)

class Tag(Model): has_and_belongs_to_many = ('Post',)

my_post = Post.create(name='My first post') personal_tag = Tag.create(name='personal') public_tag = Tag.create(name='public') my_post['tags'].add(personal_tag, public_tag) print my_post['tags'].count() # prints 2

Has many through

class Recipe(Model):
    has_many = ('SpecificSpice',)

class Chef(Model): has_many = ('SpecificSpice',)

class SpecificSpice(Model): belongs_to = ('Recipe', 'Chef')

quattro_formaggi = Recipe.create(name='Pizza Quattro Formaggi') andrei = Chef.create(name='Andrei') andreis_special_quattro_formaggi = SpecificSpice.create(chef=andrei, recipe=quattro_formaggi, oregano=True, love=True) print andreis_special_quatro_formaggi['love'] # prints True


from remodel.models import Model

class Shirt(Model): def after_init(self): self.wash()

def wash(self):
    print 'Gotta wash a shirt after creating it...'


from remodel.models import Model, after_save

class Prize(Model): @after_save def brag(self): print 'I just won a prize!'

Custom table name

class Child(Model):
    table_name = 'kids'

print Child.table_name # prints 'kids'

Custom model queries

import rethinkdb as r

class Celebrity(Model): pass

Celebrity.create(name='george clooney') Celebrity.create(name='kate winslet') upper ={'name': r.row['name'].upcase()}).run() print list(upper) # prints [{u'name': u'GEORGE CLOONEY'}, {u'name': u'KATE WINSLET'}]

Custom instance methods

class Child(Model):
    def is_minor(self):
        if 'age' in self:
            return self['age'] < 18

jack = Child.create(name='Jack', age=15) jack.is_minor() # prints True

Custom class methods

from remodel.object_handler import ObjectHandler, ObjectSet

class TripObjectHandler(ObjectHandler): def in_europe(self): return ObjectSet(self, self.query.filter({'continent': 'Europe'}))

class Trip(Model): object_handler = TripObjectHandler

Trip.create(continent='Europe', city='Paris') Trip.create(continent='Asia', city='Shanghai') Trip.create(continent='Europe', city='Dublin') print len(Trip.in_europe()) # prints 2

Viewing object fields

class Train(Model):

train = Train.create(nr=12345, destination='Paris', has_restaurant=True, classes=[1, 2]) print train.fields.as_dict()

prints {u'classes': [1, 2], u'nr': 12345, u'destination': u'Paris', u'has_restaurant': True, u'id': u'd9b8d57f-5d67-4ff7-acf8-cbf7fdd65581'}



Remodel supports various types of relationships: - has one - belongs to - has many - has and belongs to many - has many through

Defining relations

Related models are passed as tuples in a model's definition. All other aspects, such as foreign keys, indexes, lazy relation loading and relation cache are magically handled for you.

If you need precise definition for your related models, you can pass a configuration tuple instead of the string name of your related model:

    class Artist(Model):
        has_many = (('Song', 'songs', 'id', 'song_id'), 'Concert')
        # Tuple definition: (, , , )

One important thing to notice is that reverse relationships are not automatically ensured if only one end of the relationship is defined. This means that if

Artist has_many Song
Song belongs_to Artist
is not automatically enforced unless explicitly defined.

Using relations


objects doesn't mean that they are persisted. You need to manually call
on them; assuming
Profile belongs_to User
profile['user'] = User(...)

On the other side, assigning

objects automatically persist them, so there is no need for you to call
on them; assuming
Shop has_many Product
shop.add(product1, produt2)
# No need to call save() on products!

Note that certain assignments of related objects can not be performed unless one (or both) of the objects is saved. You can not save a

with a
attached without saving the
object first (when having a
GiftSize belongs_to Gift


Can be found at


The main reason for Remodel's existence was the need of a light-weight ODM for RethinkDB, one that doesn't force you to ensure a document schema, one that provides a familiar interface and one that gracefully handles relations between models.


Remodel is under active development and it is not yet production-ready.

How to contribute?

Any contribution is highly appreciated! See for more details.



We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.