High-level (new) API

High-level API provides a single point for all async ORM calls. Meet the Manager class! The idea of Manager originally comes from Django, but it’s redesigned to meet new asyncio patterns.

First of all, once Manager is initialized with database and event loop, it’s easy and safe to perform async calls. And all async operations and transactions management methods are bundled with a single object. No need to pass around database instance, event loop, etc.

Also there’s no need to connect and re-connect before executing async queries with manager! It’s all automatic. But you can run Manager.connect() or Manager.close() when you need it.

Note: code examples below are written for Python 3.5.x, it is possible to adapt them for Python 3.4.x by replacing await with yield from and async def with @asyncio.coroutine decorator. And async context managers like transaction() etc, are only possible in Python 3.5+

OK, let’s provide an example:

import asyncio
import peewee
import logging
from peewee_async import Manager, PostgresqlDatabase

loop = asyncio.new_event_loop() # Note: custom loop!
database = PostgresqlDatabase('test')
objects = Manager(database, loop=loop)

– once objects is created with specified loop, all database connections automatically will be set up on that loop. Sometimes, it’s so easy to forget to pass custom loop instance, but now it’s not a problem! Just initialize with an event loop once.

Let’s define a simple model:

class PageBlock(peewee.Model):
    key = peewee.CharField(max_length=40, unique=True)
    text = peewee.TextField(default='')

    class Meta:
        database = database

– as you can see, nothing special in this code, just plain peewee.Model definition.

Now we need to create a table for model:

PageBlock.create_table(True)

– this code is sync, and will do absolutely the same thing as would do code with regular peewee.PostgresqlDatabase. This is intentional, I believe there’s just no need to run database initialization code asynchronously! Less code, less errors.

From now we may want only async calls and treat sync as unwanted or as errors:

objects.database.allow_sync = False # this will raise AssertionError on ANY sync call

– alternatevely we can set ERROR or WARNING loggin level to database.allow_sync:

objects.database.allow_sync = logging.ERROR

Finally, let’s do something async:

async def my_async_func():
    # Add new page block
    await objects.create_or_get(
        PageBlock, key='title',
        text="Peewee is AWESOME with async!")

    # Get one by key
    title = await objects.get(PageBlock, key='title')
    print("Was:", title.text)

    # Save with new text
    title.text = "Peewee is SUPER awesome with async!"
    await objects.update(title)
    print("New:", title.text)

loop.run_until_complete(my_async_func())
loop.close()

That’s it!

Other methods for operations like selecting, deleting etc. are listed below.

Manager

class peewee_async.Manager(database=None, *, loop=None)

Async peewee models manager.

Parameters:
  • loop – (optional) asyncio event loop
  • database – (optional) async database driver

Example:

class User(peewee.Model):
    username = peewee.CharField(max_length=40, unique=True)

objects = Manager(PostgresqlDatabase('test'))

async def my_async_func():
    user0 = await objects.create(User, username='test')
    user1 = await objects.get(User, id=user0.id)
    user2 = await objects.get(User, username='test')
    # All should be the same
    print(user1.id, user2.id, user3.id)

If you don’t pass database to constructor, you should define database as a class member like that:

database = PostgresqlDatabase('test')

class MyManager(Manager):
    database = database

objects = MyManager()
Manager.database = None

Async database driver for manager. Must be provided in constructor or as a class member.

Manager.allow_sync()

Allow sync queries within context. Close the sync database connection on exit if connected.

Example:

with objects.allow_sync():
    PageBlock.create_table(True)
Manager.get(source_, *args, **kwargs)

Get the model instance.

Parameters:source – model or base query for lookup

Example:

async def my_async_func():
    obj1 = await objects.get(MyModel, id=1)
    obj2 = await objects.get(MyModel, MyModel.id==1)
    obj3 = await objects.get(MyModel.select().where(MyModel.id==1))

All will return MyModel instance with id = 1

Manager.create(model_, **data)

Create a new object saved to database.

Manager.update(obj, only=None)

Update the object in the database. Optionally, update only the specified fields. For creating a new object use create()

Parameters:only – (optional) the list/tuple of fields or field names to update
Manager.delete(obj, recursive=False, delete_nullable=False)

Delete object from database.

Manager.get_or_create(model_, defaults=None, **kwargs)

Try to get an object or create it with the specified defaults.

Return 2-tuple containing the model instance and a boolean indicating whether the instance was created.

Manager.create_or_get(model_, **kwargs)

Try to create new object with specified data. If object already exists, then try to get it by unique fields.

Manager.execute(query)

Execute query asyncronously.

Manager.prefetch(query, *subqueries)

Asynchronous version of the prefetch() from peewee.

Returns:Query that has already cached data for subqueries
Manager.count(query, clear_limit=False)

Perform COUNT aggregated query asynchronously.

Returns:number of objects in select() query
Manager.scalar(query, as_tuple=False)

Get single value from select() query, i.e. for aggregation.

Returns:result is the same as after sync query.scalar() call
Manager.connect()

Open database async connection if not connected.

Manager.close()

Close database async connection if connected.

Manager.atomic()

Similar to peewee.Database.atomic() method, but returns asynchronous context manager.

Example:

async with objects.atomic():
    await objects.create(
        PageBlock, key='intro',
        text="There are more things in heaven and earth, "
             "Horatio, than are dreamt of in your philosophy.")
    await objects.create(
        PageBlock, key='signature', text="William Shakespeare")
Manager.transaction()

Similar to peewee.Database.transaction() method, but returns asynchronous context manager.

Manager.savepoint(sid=None)

Similar to peewee.Database.savepoint() method, but returns asynchronous context manager.

Databases

class peewee_async.PostgresqlDatabase(database, thread_safe=True, autorollback=False, field_types=None, operations=None, autocommit=None, **kwargs)

PosgreSQL database driver providing single drop-in sync connection and single async connection interface.

Example:

database = PostgresqlDatabase('test')

See also: http://peewee.readthedocs.io/en/latest/peewee/api.html#PostgresqlDatabase

class peewee_async.PooledPostgresqlDatabase(database, thread_safe=True, autorollback=False, field_types=None, operations=None, autocommit=None, **kwargs)

PosgreSQL database driver providing single drop-in sync connection and async connections pool interface.

Parameters:max_connections – connections pool size

Example:

database = PooledPostgresqlDatabase('test', max_connections=20)

See also: http://peewee.readthedocs.io/en/latest/peewee/api.html#PostgresqlDatabase

class peewee_asyncext.PostgresqlExtDatabase(*args, **kwargs)

PosgreSQL database extended driver providing single drop-in sync connection and single async connection interface.

JSON fields support is always enabled, HStore supports is enabled by default, but can be disabled with register_hstore=False argument.

Example:

database = PostgresqlExtDatabase('test', register_hstore=False)

See also: https://peewee.readthedocs.io/en/latest/peewee/

playhouse.html#PostgresqlExtDatabase
class peewee_asyncext.PooledPostgresqlExtDatabase(*args, **kwargs)

PosgreSQL database extended driver providing single drop-in sync connection and async connections pool interface.

JSON fields support is always enabled, HStore supports is enabled by default, but can be disabled with register_hstore=False argument.

Parameters:max_connections – connections pool size

Example:

database = PooledPostgresqlExtDatabase('test', register_hstore=False,
                                       max_connections=20)

See also: https://peewee.readthedocs.io/en/latest/peewee/

playhouse.html#PostgresqlExtDatabase
class peewee_async.MySQLDatabase(database, thread_safe=True, autorollback=False, field_types=None, operations=None, autocommit=None, **kwargs)

MySQL database driver providing single drop-in sync connection and single async connection interface.

Example:

database = MySQLDatabase('test')

See also: http://peewee.readthedocs.io/en/latest/peewee/api.html#MySQLDatabase

class peewee_async.PooledMySQLDatabase(database, thread_safe=True, autorollback=False, field_types=None, operations=None, autocommit=None, **kwargs)

MySQL database driver providing single drop-in sync connection and async connections pool interface.

Parameters:max_connections – connections pool size

Example:

database = MySQLDatabase('test', max_connections=10)

See also: http://peewee.readthedocs.io/en/latest/peewee/api.html#MySQLDatabase