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