tortoise-orm


Nametortoise-orm JSON
Version 0.21.7 PyPI version JSON
download
home_pagehttps://github.com/tortoise/tortoise-orm
SummaryEasy async ORM for python, built with relations in mind
upload_time2024-10-14 08:05:08
maintainerNone
docs_urlNone
authorAndrey Bondar
requires_python<4.0,>=3.8
licenseApache-2.0
keywords sql mysql postgres psql sqlite aiosqlite asyncpg relational database rdbms orm object mapper async asyncio aio psycopg
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ============
Tortoise ORM
============

.. image:: https://img.shields.io/pypi/v/tortoise-orm.svg?style=flat
   :target: https://pypi.python.org/pypi/tortoise-orm
.. image:: https://pepy.tech/badge/tortoise-orm/month
   :target: https://pepy.tech/project/tortoise-orm
.. image:: https://github.com/tortoise/tortoise-orm/workflows/gh-pages/badge.svg
   :target: https://github.com/tortoise/tortoise-orm/actions?query=workflow:gh-pages
.. image:: https://github.com/tortoise/tortoise-orm/actions/workflows/ci.yml/badge.svg?branch=develop
   :target: https://github.com/tortoise/tortoise-orm/actions?query=workflow:ci
.. image:: https://coveralls.io/repos/github/tortoise/tortoise-orm/badge.svg
   :target: https://coveralls.io/github/tortoise/tortoise-orm
.. image:: https://app.codacy.com/project/badge/Grade/844030d0cb8240d6af92c71bfac764ff
   :target: https://www.codacy.com/gh/tortoise/tortoise-orm/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=tortoise/tortoise-orm&amp;utm_campaign=Badge_Grade

Introduction
============

Tortoise ORM is an easy-to-use ``asyncio`` ORM *(Object Relational Mapper)* inspired by Django.

Tortoise ORM was built with relations in mind and admiration for the excellent and popular Django ORM.
It's engraved in its design that you are working not with just tables, you work with relational data.

You can find the docs at `Documentation <https://tortoise.github.io>`_

.. note::
   Tortoise ORM is a young project and breaking changes are to be expected.
   We keep a `Changelog <https://tortoise.github.io/CHANGELOG.html>`_ and it will have possible breakage clearly documented.

Tortoise ORM is supported on CPython >= 3.8 for SQLite, MySQL and PostgreSQL and Microsoft SQL Server and Oracle.

Why was Tortoise ORM built?
---------------------------

Python has many existing and mature ORMs, unfortunately they are designed with an opposing paradigm of how I/O gets processed.
``asyncio`` is relatively new technology that has a very different concurrency model, and the largest change is regarding how I/O is handled.

However, Tortoise ORM is not the first attempt of building an ``asyncio`` ORM. While there are many cases of developers attempting to map synchronous Python ORMs to the async world, initial attempts did not have a clean API.

Hence we started Tortoise ORM.

Tortoise ORM is designed to be functional, yet familiar, to ease the migration of developers wishing to switch to ``asyncio``.

It also performs well when compared to other Python ORMs. In `our benchmarks <https://github.com/tortoise/orm-benchmarks>`_, where we measure different read and write operations (rows/sec, more is better), it's trading places with Pony ORM:

.. image:: https://raw.githubusercontent.com/tortoise/tortoise-orm/develop/docs/ORM_Perf.png
    :target: https://github.com/tortoise/orm-benchmarks

How is an ORM useful?
---------------------

When you build an application or service that uses a relational database, there is a point where you can't get away with just using parameterized queries or even query builder. You just keep repeating yourself, writing slightly different code for each entity.
Code has no idea about relations between data, so you end up concatenating your data almost manually.
It is also easy to make mistakes in how you access your database, which can be exploited by SQL-injection attacks.
Your data rules are also distributed, increasing the complexity of managing your data, and even worse, could lead to those rules being applied inconsistently.

An ORM (Object Relational Mapper) is designed to address these issues, by centralising your data model and data rules, ensuring that your data is managed safely (providing immunity to SQL-injection) and keeping track of relationships so you don't have to.

Getting Started
===============

Installation
------------
First you have to install Tortoise ORM like this:

.. code-block:: bash

    pip install tortoise-orm

You can also install with your db driver (`aiosqlite` is builtin):

.. code-block:: bash

    pip install "tortoise-orm[asyncpg]"


For `MySQL`:

.. code-block:: bash

    pip install "tortoise-orm[asyncmy]"

For `Microsoft SQL Server`/`Oracle` (**not fully tested**):

.. code-block:: bash

    pip install "tortoise-orm[asyncodbc]"

Quick Tutorial
--------------

The primary entity of tortoise is ``tortoise.models.Model``.
You can start writing models like this:


.. code-block:: python3

    from tortoise.models import Model
    from tortoise import fields

    class Tournament(Model):
        id = fields.IntField(primary_key=True)
        name = fields.TextField()

        def __str__(self):
            return self.name


    class Event(Model):
        id = fields.IntField(primary_key=True)
        name = fields.TextField()
        tournament = fields.ForeignKeyField('models.Tournament', related_name='events')
        participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team')

        def __str__(self):
            return self.name


    class Team(Model):
        id = fields.IntField(primary_key=True)
        name = fields.TextField()

        def __str__(self):
            return self.name


After you defined all your models, tortoise needs you to init them, in order to create backward relations between models and match your db client with the appropriate models.

You can do it like this:

.. code-block:: python3

    from tortoise import Tortoise

    async def init():
        # Here we connect to a SQLite DB file.
        # also specify the app name of "models"
        # which contain models from "app.models"
        await Tortoise.init(
            db_url='sqlite://db.sqlite3',
            modules={'models': ['app.models']}
        )
        # Generate the schema
        await Tortoise.generate_schemas()


Here we create a connection to an SQLite database in the local directory called ``db.sqlite3``. Then we discover and initialise the models.

Tortoise ORM currently supports the following databases:

* `SQLite` (requires ``aiosqlite``)
* `PostgreSQL` (requires ``asyncpg``)
* `MySQL` (requires ``asyncmy``)
* `Microsoft SQL Server`/`Oracle` (requires ``asyncodbc``)

``generate_schema`` generates the schema on an empty database. Tortoise generates schemas in safe mode by default which
includes the ``IF NOT EXISTS`` clause, so you may include it in your main code.


After that you can start using your models:

.. code-block:: python3

    # Create instance by save
    tournament = Tournament(name='New Tournament')
    await tournament.save()

    # Or by .create()
    await Event.create(name='Without participants', tournament=tournament)
    event = await Event.create(name='Test', tournament=tournament)
    participants = []
    for i in range(2):
        team = await Team.create(name='Team {}'.format(i + 1))
        participants.append(team)

    # M2M Relationship management is quite straightforward
    # (also look for methods .remove(...) and .clear())
    await event.participants.add(*participants)

    # You can query a related entity with async for
    async for team in event.participants:
        pass

    # After making a related query you can iterate with regular for,
    # which can be extremely convenient when using it with other packages,
    # for example some kind of serializers with nested support
    for team in event.participants:
        pass


    # Or you can make a preemptive call to fetch related objects
    selected_events = await Event.filter(
        participants=participants[0].id
    ).prefetch_related('participants', 'tournament')

    # Tortoise supports variable depth of prefetching related entities
    # This will fetch all events for Team and in those events tournaments will be prefetched
    await Team.all().prefetch_related('events__tournament')

    # You can filter and order by related models too
    await Tournament.filter(
        events__name__in=['Test', 'Prod']
    ).order_by('-events__participants__name').distinct()

Migration
=========

Tortoise ORM uses `Aerich <https://github.com/tortoise/aerich>`_ as its database migration tool, see more detail at its `docs <https://github.com/tortoise/aerich>`_.

Contributing
============

Please have a look at the `Contribution Guide <docs/CONTRIBUTING.rst>`_.

ThanksTo
========

Powerful Python IDE `Pycharm <https://www.jetbrains.com/pycharm/>`_
from `Jetbrains <https://jb.gg/OpenSourceSupport>`_.

.. image:: https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg
    :target: https://jb.gg/OpenSourceSupport

License
=======

This project is licensed under the Apache License - see the `LICENSE.txt <LICENSE.txt>`_ file for details.


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/tortoise/tortoise-orm",
    "name": "tortoise-orm",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.8",
    "maintainer_email": null,
    "keywords": "sql, mysql, postgres, psql, sqlite, aiosqlite, asyncpg, relational, database, rdbms, orm, object mapper, async, asyncio, aio, psycopg",
    "author": "Andrey Bondar",
    "author_email": "andrey@bondar.ru",
    "download_url": "https://files.pythonhosted.org/packages/e8/0e/ad8e7554b0259072887d602617a67ef21055e1d8aa061936e381ecc1a9a5/tortoise_orm-0.21.7.tar.gz",
    "platform": null,
    "description": "============\nTortoise ORM\n============\n\n.. image:: https://img.shields.io/pypi/v/tortoise-orm.svg?style=flat\n   :target: https://pypi.python.org/pypi/tortoise-orm\n.. image:: https://pepy.tech/badge/tortoise-orm/month\n   :target: https://pepy.tech/project/tortoise-orm\n.. image:: https://github.com/tortoise/tortoise-orm/workflows/gh-pages/badge.svg\n   :target: https://github.com/tortoise/tortoise-orm/actions?query=workflow:gh-pages\n.. image:: https://github.com/tortoise/tortoise-orm/actions/workflows/ci.yml/badge.svg?branch=develop\n   :target: https://github.com/tortoise/tortoise-orm/actions?query=workflow:ci\n.. image:: https://coveralls.io/repos/github/tortoise/tortoise-orm/badge.svg\n   :target: https://coveralls.io/github/tortoise/tortoise-orm\n.. image:: https://app.codacy.com/project/badge/Grade/844030d0cb8240d6af92c71bfac764ff\n   :target: https://www.codacy.com/gh/tortoise/tortoise-orm/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=tortoise/tortoise-orm&amp;utm_campaign=Badge_Grade\n\nIntroduction\n============\n\nTortoise ORM is an easy-to-use ``asyncio`` ORM *(Object Relational Mapper)* inspired by Django.\n\nTortoise ORM was built with relations in mind and admiration for the excellent and popular Django ORM.\nIt's engraved in its design that you are working not with just tables, you work with relational data.\n\nYou can find the docs at `Documentation <https://tortoise.github.io>`_\n\n.. note::\n   Tortoise ORM is a young project and breaking changes are to be expected.\n   We keep a `Changelog <https://tortoise.github.io/CHANGELOG.html>`_ and it will have possible breakage clearly documented.\n\nTortoise ORM is supported on CPython >= 3.8 for SQLite, MySQL and PostgreSQL and Microsoft SQL Server and Oracle.\n\nWhy was Tortoise ORM built?\n---------------------------\n\nPython has many existing and mature ORMs, unfortunately they are designed with an opposing paradigm of how I/O gets processed.\n``asyncio`` is relatively new technology that has a very different concurrency model, and the largest change is regarding how I/O is handled.\n\nHowever, Tortoise ORM is not the first attempt of building an ``asyncio`` ORM. While there are many cases of developers attempting to map synchronous Python ORMs to the async world, initial attempts did not have a clean API.\n\nHence we started Tortoise ORM.\n\nTortoise ORM is designed to be functional, yet familiar, to ease the migration of developers wishing to switch to ``asyncio``.\n\nIt also performs well when compared to other Python ORMs. In `our benchmarks <https://github.com/tortoise/orm-benchmarks>`_, where we measure different read and write operations (rows/sec, more is better), it's trading places with Pony ORM:\n\n.. image:: https://raw.githubusercontent.com/tortoise/tortoise-orm/develop/docs/ORM_Perf.png\n    :target: https://github.com/tortoise/orm-benchmarks\n\nHow is an ORM useful?\n---------------------\n\nWhen you build an application or service that uses a relational database, there is a point where you can't get away with just using parameterized queries or even query builder. You just keep repeating yourself, writing slightly different code for each entity.\nCode has no idea about relations between data, so you end up concatenating your data almost manually.\nIt is also easy to make mistakes in how you access your database, which can be exploited by SQL-injection attacks.\nYour data rules are also distributed, increasing the complexity of managing your data, and even worse, could lead to those rules being applied inconsistently.\n\nAn ORM (Object Relational Mapper) is designed to address these issues, by centralising your data model and data rules, ensuring that your data is managed safely (providing immunity to SQL-injection) and keeping track of relationships so you don't have to.\n\nGetting Started\n===============\n\nInstallation\n------------\nFirst you have to install Tortoise ORM like this:\n\n.. code-block:: bash\n\n    pip install tortoise-orm\n\nYou can also install with your db driver (`aiosqlite` is builtin):\n\n.. code-block:: bash\n\n    pip install \"tortoise-orm[asyncpg]\"\n\n\nFor `MySQL`:\n\n.. code-block:: bash\n\n    pip install \"tortoise-orm[asyncmy]\"\n\nFor `Microsoft SQL Server`/`Oracle` (**not fully tested**):\n\n.. code-block:: bash\n\n    pip install \"tortoise-orm[asyncodbc]\"\n\nQuick Tutorial\n--------------\n\nThe primary entity of tortoise is ``tortoise.models.Model``.\nYou can start writing models like this:\n\n\n.. code-block:: python3\n\n    from tortoise.models import Model\n    from tortoise import fields\n\n    class Tournament(Model):\n        id = fields.IntField(primary_key=True)\n        name = fields.TextField()\n\n        def __str__(self):\n            return self.name\n\n\n    class Event(Model):\n        id = fields.IntField(primary_key=True)\n        name = fields.TextField()\n        tournament = fields.ForeignKeyField('models.Tournament', related_name='events')\n        participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team')\n\n        def __str__(self):\n            return self.name\n\n\n    class Team(Model):\n        id = fields.IntField(primary_key=True)\n        name = fields.TextField()\n\n        def __str__(self):\n            return self.name\n\n\nAfter you defined all your models, tortoise needs you to init them, in order to create backward relations between models and match your db client with the appropriate models.\n\nYou can do it like this:\n\n.. code-block:: python3\n\n    from tortoise import Tortoise\n\n    async def init():\n        # Here we connect to a SQLite DB file.\n        # also specify the app name of \"models\"\n        # which contain models from \"app.models\"\n        await Tortoise.init(\n            db_url='sqlite://db.sqlite3',\n            modules={'models': ['app.models']}\n        )\n        # Generate the schema\n        await Tortoise.generate_schemas()\n\n\nHere we create a connection to an SQLite database in the local directory called ``db.sqlite3``. Then we discover and initialise the models.\n\nTortoise ORM currently supports the following databases:\n\n* `SQLite` (requires ``aiosqlite``)\n* `PostgreSQL` (requires ``asyncpg``)\n* `MySQL` (requires ``asyncmy``)\n* `Microsoft SQL Server`/`Oracle` (requires ``asyncodbc``)\n\n``generate_schema`` generates the schema on an empty database. Tortoise generates schemas in safe mode by default which\nincludes the ``IF NOT EXISTS`` clause, so you may include it in your main code.\n\n\nAfter that you can start using your models:\n\n.. code-block:: python3\n\n    # Create instance by save\n    tournament = Tournament(name='New Tournament')\n    await tournament.save()\n\n    # Or by .create()\n    await Event.create(name='Without participants', tournament=tournament)\n    event = await Event.create(name='Test', tournament=tournament)\n    participants = []\n    for i in range(2):\n        team = await Team.create(name='Team {}'.format(i + 1))\n        participants.append(team)\n\n    # M2M Relationship management is quite straightforward\n    # (also look for methods .remove(...) and .clear())\n    await event.participants.add(*participants)\n\n    # You can query a related entity with async for\n    async for team in event.participants:\n        pass\n\n    # After making a related query you can iterate with regular for,\n    # which can be extremely convenient when using it with other packages,\n    # for example some kind of serializers with nested support\n    for team in event.participants:\n        pass\n\n\n    # Or you can make a preemptive call to fetch related objects\n    selected_events = await Event.filter(\n        participants=participants[0].id\n    ).prefetch_related('participants', 'tournament')\n\n    # Tortoise supports variable depth of prefetching related entities\n    # This will fetch all events for Team and in those events tournaments will be prefetched\n    await Team.all().prefetch_related('events__tournament')\n\n    # You can filter and order by related models too\n    await Tournament.filter(\n        events__name__in=['Test', 'Prod']\n    ).order_by('-events__participants__name').distinct()\n\nMigration\n=========\n\nTortoise ORM uses `Aerich <https://github.com/tortoise/aerich>`_ as its database migration tool, see more detail at its `docs <https://github.com/tortoise/aerich>`_.\n\nContributing\n============\n\nPlease have a look at the `Contribution Guide <docs/CONTRIBUTING.rst>`_.\n\nThanksTo\n========\n\nPowerful Python IDE `Pycharm <https://www.jetbrains.com/pycharm/>`_\nfrom `Jetbrains <https://jb.gg/OpenSourceSupport>`_.\n\n.. image:: https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg\n    :target: https://jb.gg/OpenSourceSupport\n\nLicense\n=======\n\nThis project is licensed under the Apache License - see the `LICENSE.txt <LICENSE.txt>`_ file for details.\n\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "Easy async ORM for python, built with relations in mind",
    "version": "0.21.7",
    "project_urls": {
        "Documentation": "https://tortoise-orm.readthedocs.io",
        "Homepage": "https://github.com/tortoise/tortoise-orm",
        "Repository": "https://github.com/tortoise/tortoise-orm.git"
    },
    "split_keywords": [
        "sql",
        " mysql",
        " postgres",
        " psql",
        " sqlite",
        " aiosqlite",
        " asyncpg",
        " relational",
        " database",
        " rdbms",
        " orm",
        " object mapper",
        " async",
        " asyncio",
        " aio",
        " psycopg"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "00e4918587b57062e83ce230635b5e4611cd192967c1fef9e08936e77f9ba2b9",
                "md5": "ebe2fc0be175aa309ac075664d0adfca",
                "sha256": "2229925885461f424673223ea1875bd5e6961384c766833af55a1ea11a9b25eb"
            },
            "downloads": -1,
            "filename": "tortoise_orm-0.21.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ebe2fc0be175aa309ac075664d0adfca",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.8",
            "size": 175702,
            "upload_time": "2024-10-14T08:05:07",
            "upload_time_iso_8601": "2024-10-14T08:05:07.257311Z",
            "url": "https://files.pythonhosted.org/packages/00/e4/918587b57062e83ce230635b5e4611cd192967c1fef9e08936e77f9ba2b9/tortoise_orm-0.21.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e80ead8e7554b0259072887d602617a67ef21055e1d8aa061936e381ecc1a9a5",
                "md5": "328373e7e6112eab38984d6c1c7caf41",
                "sha256": "8a790a931828aa37ac364b344c561e603422aced2af5e403f6790575da0f19c5"
            },
            "downloads": -1,
            "filename": "tortoise_orm-0.21.7.tar.gz",
            "has_sig": false,
            "md5_digest": "328373e7e6112eab38984d6c1c7caf41",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.8",
            "size": 138689,
            "upload_time": "2024-10-14T08:05:08",
            "upload_time_iso_8601": "2024-10-14T08:05:08.635946Z",
            "url": "https://files.pythonhosted.org/packages/e8/0e/ad8e7554b0259072887d602617a67ef21055e1d8aa061936e381ecc1a9a5/tortoise_orm-0.21.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-14 08:05:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tortoise",
    "github_project": "tortoise-orm",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "tortoise-orm"
}
        
Elapsed time: 0.40523s