GINO Is Not ORM - a Python asyncio ORM on SQLAlchemy core.
Clone or download
wwwjfy Merge pull request #395 from wwwjfy/ext-ssl
refs #387, add ssl parameters for all extensions
Latest commit 2fb8179 Nov 19, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Refs #228, add aiocontextvars and some others in GitHub issue template May 24, 2018
.tx Chinese documentation base Mar 8, 2018
docs Fixes #308, refs #365, update docs Oct 25, 2018
gino refs #387, add ssl parameters for all extensions Nov 18, 2018
tests refs #387, add ssl parameters for all extensions Nov 18, 2018
.coveragerc Fix coverage Jul 27, 2018
.editorconfig Cut crom https://github.com/audreyr/cookiecutter-pypackage Jul 21, 2017
.gitignore Test translation Mar 8, 2018
.travis.yml refs #265, add py37 to travis Jul 6, 2018
AUTHORS.rst Refs #351, make none_as_none default and prepare 0.8 release Sep 30, 2018
CODE_OF_CONDUCT.md Create CODE_OF_CONDUCT.md Aug 21, 2017
CONTRIBUTING.rst Update contribution docs, reorder requirements May 21, 2018
HISTORY.rst HISTORY for 0.8.0 Oct 16, 2018
LICENSE License year Feb 26, 2018
MANIFEST.in Fix for pyup. Sep 2, 2017
Makefile Fix sphinx warnings May 24, 2018
PATRONS.md Update PATRONS.md Nov 18, 2018
README.rst Update documentation for aiocontextvars 0.2 Sep 10, 2018
environment.yml Fix docs build Apr 26, 2018
pytest.ini specify path to collect tests Aug 1, 2017
readthedocs.yml Fix readthedocs Sep 3, 2017
requirements.txt Update asyncpg from 0.18.1 to 0.18.2 Nov 10, 2018
requirements_dev.txt set pyup to minor only for all depedencies Nov 17, 2018
setup.cfg Bump version: 0.7.6 → 0.8.0 Oct 16, 2018
setup.py Bump version: 0.7.6 → 0.8.0 Oct 16, 2018
tox.ini fix false warning by flake8 3.6.0 Oct 24, 2018
travis_pypi_setup.py Cut crom https://github.com/audreyr/cookiecutter-pypackage Jul 21, 2017

README.rst

GINO

Documentation Status Updates Gitter chat

GINO - GINO Is Not ORM - is a lightweight asynchronous ORM built on top of SQLAlchemy core for Python asyncio. Now (early 2018) GINO supports only one dialect asyncpg.

  • Free software: BSD license
  • Requires: Python 3.5

Documentation

Features

  • Robust SQLAlchemy-asyncpg bi-translator with no hard hack
  • Asynchronous SQLAlchemy-alike engine and connection
  • Asynchronous dialect API
  • Asynchronous-friendly CRUD objective models
  • Well-considered contextual connection and transaction management
  • Reusing native SQLAlchemy core to build queries with grammar sugars
  • Support Sanic, Tornado and aiohttp
  • Rich PostgreSQL JSONB support

Installation

pip install gino

Showcase

import asyncio
from gino import Gino

db = Gino()


class User(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer(), primary_key=True)
    nickname = db.Column(db.Unicode(), default='noname')


async def main():
    await db.set_bind('postgresql://localhost/gino')

    # Create tables
    await db.gino.create_all()

    # Create object, `id` is assigned by database
    u1 = await User.create(nickname='fantix')
    print(u1.id, u1.nickname)  # 1 fantix

    # Returns all user objects with "d" in their nicknames
    users = await User.query.where(User.nickname.contains('d')).gino.all()
    print(users)  # [<User object>, <User object>]

    # Find one user object, None if not found
    user = await User.query.where(User.nickname == 'daisy').gino.first()
    print(user)  # <User object> or None

    # Execute complex statement and return command status
    status, result = await User.update.values(
        nickname='No.' + db.cast(User.id, db.Unicode),
    ).where(
        User.id > 10,
    ).gino.status()
    print(status)  # UPDATE 8

    # Iterate over the results of a large query in a transaction as required
    async with db.transaction():
        async for u in User.query.order_by(User.id).gino.iterate():
            print(u.id, u.nickname)


asyncio.get_event_loop().run_until_complete(main())

About The Name

About the name GINO Is Not ORM - because I don't really like ORM (smile). GINO does perform the Object-Relational Mapping work under the Data Mapper Pattern, but it is just not a traditional ORM. The Objects in GINO are completely stateless from database - they are pure plain Python objects in memory. Changing their attribute values does not make them "dirty" - or in a different way of thinking they are always "dirty". Any access to database must be explicitly executed. Using GINO is more like making up SQL clauses with Models and Objects, executing them to make changes in database, or loading data from database and wrapping the results with Objects again. Objects are just row data containers, you are still dealing with SQL which is represented by Models and SQLAlchemy core grammars. Besides if you don't like ORM at all, you can use GINO without ORM:

import sqlalchemy as sa

metadata = sa.MetaData()

user = sa.Table(
    'users', metadata,
    sa.Column('id', sa.BigInteger(), primary_key=True),
    sa.Column('nickname', sa.Unicode()),
)


import gino

async def main():
    e = await gino.create_engine('postgresql://localhost/gino')
    users = await e.all(sa.select([user]))
    print(users)
    # prints something like this:
    # [(1, 'fantix'), (2, 'fantix'), (3, 'fantix'), (5, 'fantix')]


import asyncio

asyncio.get_event_loop().run_until_complete(main())

or a bit more GINO-ish:

from gino import Gino

db = Gino()

user = db.Table(
    'users', db,
    db.Column('id', db.BigInteger(), primary_key=True),
    db.Column('nickname', db.Unicode()),
)

async def main():
    async with db.with_bind('postgresql://localhost/gino'):
        users = await db.select([user]).gino.all()
        print(users)


import asyncio

asyncio.get_event_loop().run_until_complete(main())

Contribute

There are a few tasks in GitHub issues marked as help wanted. Please feel free to take any of them and pull requests are greatly welcome.

To run tests (please read more in CONTRIBUTING.rst):

$ python setup.py test

Meanwhile, these are also very much appreciated:

Projects using GINO

  • AintQ - asyncio task queue on PostgreSQL
  • ExchangeratesAPI - Foreign exchange rates API with currency conversion

Credits

Credit goes to all contributors listed or not 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.

Special thanks to my wife Daisy and her outsourcing company DecentFoX Studio, for offering me the opportunity to build this project. We are open for global software project outsourcing on Python, iOS and Android development. And we are hiring!