GINO Is Not ORM - a Python ORM on asyncpg and SQLAlchemy core.
- Free software: BSD license
- Documentation: https://gino.readthedocs.io.
There’s been a lot of words about ORM a.k.a. Object-relational mapping - good or bad - as well as a lot of ORM libraries in Python. It is crucial to pick a most suitable one for your project, and for your team. GINO tries to stay in the middle between ORM and non-ORM, offering an extremely simple option.
GINO tries to define database tables with plain old Python objects - they are normal Python objects, a rollback doesn’t magically change their values. Any database operations are explicit. There are no dirty models, no sessions, no magic. You have concrete control to the database, through a convenient object interface. That’s it.
GINO depends on asyncpg, which means it works only for PostgreSQL and asyncio, which means Python 3 is required - actually 3.6 required for now. Based on SQLAlchemy, gate to its ecosystem is open - feel free to use e.g. Alembic to manage your schema changes. And we specially designed a few candies for the Sanic server.
A piece of code is worth a thousand words:
from gino import Gino from sqlalchemy import Column, BigInteger, Unicode db = Gino() class User(db.Model): __tablename__ = 'users' id = Column(BigInteger(), primary_key=True) nickname = Column(Unicode(), default='noname')
This is quite similar to SQLAlchemy ORM, but it is actually SQLAlchemy core:
- db = Gino() is actually a sqlalchemy.MetaData object
- class User actually defines a sqlalchemy.Table at User.__table__
Other than that, User is just a normal Python object:
u = User() u.id = 7 u.id += 2 u.nickname = 'fantix'
Think as if User is defined normally (keep in imagination, not an example):
class User: def __init__(self): self.id = None self.nickname = None
However on class level, you have access to SQLAlchemy columns, which allows you to do SQLAlchemy core programming:
from sqlalchemy import select query = select([User.nickname]).where(User.id == 9)
The Gino object offers a SQLAlchemy dialect for asyncpg, allowing to execute the query in asyncpg:
import asyncpg conn = await asyncpg.connect('postgresql://localhost/gino') query, params = db.compile(query) rv = await conn.fetchval(query, *params)
And GINO offers some sugars:
u1 = await User.get(9, bind=conn) u2 = await User.create(bind=conn, nickname=u1.nickname)) async with conn.transaction(): query, params = db.compile(User.query.where(User.id > 2)) async for u in User.map(conn.cursor(query, *params)): print(u.id, u.nickname)
- Declare SQLAlchemy core tables with plain model objects, no ORM magic
- Easily construct queries and execute them through asyncpg
There’re a few usage examples in the examples directory.
To run tests:
python setup.py test
Credit goes to all contributors listed in the AUTHORS file. This project is inspired by asyncpgsa, peewee-async and asyncorm. asyncpg and SQLAlchemy as the dependencies did most of the heavy lifting. This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
- Support SQLAlchemy result processor
- Added rich support on JSON/JSONB
- Bug fixes
- Added update and delete API
- Changed API, no longer reuses asyncpg API
- Added db.bind
- API changed: parameter conn renamed to optional bind
- Delegated asyncpg Pool with db.create_pool
- Internal enhancement and bug fixes
- First release on PyPI.
Release history Release notifications | RSS feed
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.