resync-orm

An ORM-like wrapper for the rethinkdb asyncio driver


Keywords
rethink, rethinkdb, asyncio
License
BSD-3-Clause
Install
pip install resync-orm==0.2.1

Documentation

Introduction

Resync is a Django-ORM inspired wrapper around the official rethinkdb driver's (currently undocumented) asyncio connection class.

Usage Examples

import asyncio
import resync
from resync import fields
from resync.models import Model, NestedDocument

from myapp.auth.models import User


class Grommet(NestedDocument):
    """
    Nested documents don't have a table associated, but allow you to define a
    schema for arbitrary json sub-documents in a model.
    """
    weight = fields.FloatField()
    enabled = fields.BooleanField(default=False)


class Widget(Model):
    """
    Model classes refer to a table in the database.  By default, the table
    name is the lowercased name of the class.
    """

    id = fields.StrField()
    grommet = fields.NestedDocumentField(Grommet)
    foo = fields.StrField()
    owner = fields.ForeignKeyField(User)


async def create_widget(user: User) -> None:
    """
    Model objects can be created and manipulated like ordinary python objects,
    then saved to the database.
    """
    new_widget = Widget(owner=user, foo='bar')
    new_widget.grommet = Grommet(weight=15.0)
    await new_widget.save()
    print(new_widget.id)  # '45226082-976e-4226-b2c7-0d2c86c45b73': generated by rethinkdb


async def get_widget_by_id(id: str) -> Widget:
    """
    Use the 'objects' class attribute to query the database to retrieve an
    instance.
    """
    widget = await Widget.objects.get(id=id)
    return widget


async def get_all_widgets() -> typings.List[Widget]:
    """
    Querysets can be `await`ed to get all the results in a list ...
    """
    widgets = await Widget.objects.all()
    return widgets


async def send_all_widgets_to_socket(socket: aiohttp.web.WebSocketResponse) -> None:
    """
    ... or iterated over using `async for`
    """
    async for widget in Widget.objects.all():
        serializer = MyWidgetSerializer(widget)
        socket.send(serializer.data)


async def rename_all_widgets() -> None:
    """
    Make simple changes to the database in a single query without extracting
    the objects to python code.
    """
    await Widget.objects.all().update(foo='baz')


async def get_enabled_widgets_for_user(user: User) -> typings.List[Widget]:
    """
    Querying related fields works similarly to django, returning a queryset
    that can be manipulated as normal
    """
    ret = []
    async for widget in user.widget_set.filter(enabled=True):
        ret.append(widget)
    return ret


def main():
    """
    Resync deals transparently with connections, managing a connection pool to
    reuse open connections when available.
    """
    resync.setup({
        'host': 'my.rethinkdb.fqdn',
        'db': 'my_database_name',
        'user': 'test',
        'password': '123456'
    })  # These arguments are passed to rethinkdb.connect
        # (docs: https://www.rethinkdb.com/api/python/connect/)

    loop = asyncio.get_event_loop()
    fut = asyncio.ensure_future(get_all_widgets())
    loop.run_until_complete(fut)
    print(fut.result())  # List of widgets...

    teardown = asyncio.ensure_future(resync.teardown())
    loop.run_until_complete(teardown)  # Closes all connections.
    loop.close()

TODO

  • Tests
  • Docs

Contributors