Connections¶

This document describes how to access database connections in Tortoise ORM.

Accessing Connections¶

Tortoise ORM provides multiple ways to access database connections:

The simplest way to access connections:

from tortoise import Tortoise

# Get a specific connection by alias
conn = Tortoise.get_connection("default")

# Execute raw queries
result = await conn.execute_query('SELECT * FROM "user"')

Via Helper Functions¶

For more direct access to the connection handler:

from tortoise.connection import get_connection, get_connections

# Get a specific connection
conn = get_connection("default")

# Get the connection handler (access to all connections)
handler = get_connections()
all_connections = handler.all()

Via Context (Advanced)¶

When working with explicit contexts:

from tortoise.context import TortoiseContext

async with TortoiseContext() as ctx:
    await ctx.init(db_url="sqlite://:memory:", modules={"models": ["myapp.models"]})

    # Access connections via context
    conn = ctx.connections.get("default")

Connection Configuration¶

Connections are configured when calling Tortoise.init():

await Tortoise.init(
    config={
        "connections": {
            "default": {
                "engine": "tortoise.backends.sqlite",
                "credentials": {"file_path": "example.sqlite3"},
            }
        },
        "apps": {
            "models": {"models": ["__main__"], "default_connection": "default"}
        },
    }
)

Or using a DB URL:

await Tortoise.init(
    db_url="sqlite://example.sqlite3",
    modules={"models": ["__main__"]}
)

Multiple Databases¶

Configure multiple connections for different databases:

await Tortoise.init(
    config={
        "connections": {
            "default": "sqlite://primary.sqlite3",
            "secondary": "postgres://user:pass@localhost:5432/secondary",
        },
        "apps": {
            "primary_models": {
                "models": ["myapp.primary_models"],
                "default_connection": "default",
            },
            "secondary_models": {
                "models": ["myapp.secondary_models"],
                "default_connection": "secondary",
            }
        },
    }
)

# Access specific connections
primary_conn = Tortoise.get_connection("default")
secondary_conn = Tortoise.get_connection("secondary")

Please refer to this example for a detailed demonstration.

Closing Connections¶

Always close connections when shutting down your application:

# Close all connections
await Tortoise.close_connections()

# Or via helper function
from tortoise.connection import get_connections
await get_connections().close_all()

In framework integrations, this is typically handled automatically on shutdown.

Connection Lifecycle¶

Connections are created lazily when first accessed and are managed by the ConnectionHandler class. Each TortoiseContext has its own ConnectionHandler, providing isolation between different contexts (useful for testing).

# Connection is created on first access
conn = Tortoise.get_connection("default")

# Same connection is returned on subsequent calls
conn2 = Tortoise.get_connection("default")
assert conn is conn2

# Closing discards the connection
await Tortoise.close_connections()

# Next access creates a new connection
conn3 = Tortoise.get_connection("default")
assert conn is not conn3

Event Loop Handling¶

Some database drivers (asyncpg, aiomysql) bind their connection pools to the event loop that created them. If the loop changes – for example, when using function-scoped pytest fixtures or Starlette’s TestClient – the old pool becomes unusable.

Tortoise handles this automatically: when ConnectionHandler.get() detects that the current event loop differs from the one the connection was created on, it transparently creates a fresh connection.

In production, a loop change usually indicates a bug (e.g., mixing sync/async code). A TortoiseLoopSwitchWarning is emitted so you can investigate:

import warnings
from tortoise.warnings import TortoiseLoopSwitchWarning

# Suppress if you know what you're doing
warnings.filterwarnings("ignore", category=TortoiseLoopSwitchWarning)

In tests, tortoise_test_context() suppresses this warning automatically. No special configuration needed.

Backend Loop Binding¶

Backend

Bound?

Notes

asyncpg

Yes

Pool stores loop at creation time

aiomysql/asyncmy

Yes

Pool stores loop at creation time

psycopg

No

Uses running loop per-operation

aiosqlite

Partial

Grabs loop per-operation, not at creation

asyncodbc (MSSQL/Oracle)

No

Per-operation loop resolution

API Reference¶

Helper Functions¶

tortoise.connection.get_connection(alias)[source]¶

Get a database connection by alias from the current context.

This is a convenience function. Prefer accessing connections directly via context: ctx.connections.get(alias)

Parameters:¶
alias¶

The connection alias (e.g., “default”)

Raises:¶

ConfigurationError – If no context is active or connection not found

Return type:¶

BaseDBAsyncClient

tortoise.connection.get_connections()[source]¶

Get the ConnectionHandler from the current context.

This is a convenience function. Prefer accessing connections directly via context: ctx.connections

Raises:¶

ConfigurationError – If no context is active

Return type:¶

ConnectionHandler

ConnectionHandler Class¶

class tortoise.connection.ConnectionHandler[source]¶

Connection management for a single TortoiseContext.

Each TortoiseContext owns its own ConnectionHandler instance with isolated storage.

all()[source]¶

Returns a list of connection objects from the storage in the current context.

Return type:¶

list

async close_all(discard=True)[source]¶

Closes all connections in the storage in the current context.

All closed connections will be removed from the storage by default.

Parameters:¶
discard=True¶

If False, all connection objects are closed but retained in the storage.

Return type:¶

None

property db_config : DBConfigType¶

Return the DB config.

This is the same config passed to the Tortoise.init method while initialization.

Raises:¶

ConfigurationError – If this property is accessed before calling the Tortoise.init method.

Return type:¶

DBConfigType

discard(conn_alias)[source]¶

Discards the given alias from the storage in the current context.

Parameters:¶
conn_alias¶

The alias for which the connection object should be discarded.

Important

Make sure to have called conn.close() for the provided alias before calling this method else there would be a connection leak (dangling connection).

Return type:¶

tortoise.backends.base.client.BaseDBAsyncClient | None

get(conn_alias)[source]¶

Return the connection object for the given alias, creating it if needed.

If the connection’s event loop has changed (e.g., in a test with a new event loop), the connection is transparently replaced with a fresh one and a TortoiseLoopSwitchWarning is emitted.

Used for accessing the low-level connection object (BaseDBAsyncClient) for the given alias.

Parameters:¶
conn_alias¶

The alias for which the connection has to be fetched

Raises:¶

ConfigurationError – If the connection alias does not exist.

Return type:¶

BaseDBAsyncClient

reset(token)[source]¶

Reset the connection storage to the previous context state.

Restores the connection state for all aliases to what it was before the set() call.

Parameters:¶
token : tortoise.connection.ConnectionToken | None¶

The token returned by the set() method. Can be None (no-op).

Return type:¶

None

set(conn_alias, conn_obj)[source]¶

Sets the given alias to the provided connection object for the current task.

Parameters:¶
conn_alias¶

The alias to set the connection for.

conn_obj¶

The connection object that needs to be set for this alias.

Return type:¶

ConnectionToken

Returns:¶

A token that can be used to restore the previous context via reset().

Note

This method is primarily used by transactions to temporarily replace a connection with a transaction client. Call reset() with the returned token to restore the original connection when the transaction completes.

Migration from Legacy API¶

If you’re upgrading from an older version that used the connections singleton, see the Migration Guide: Tortoise 1.0 for details.

Note

The connections singleton still works but is deprecated. It now acts as a proxy that delegates to the current context’s ConnectionHandler. New code should use get_connection() / get_connections() or Tortoise.get_connection().

Quick reference:

API Migration¶

Old Pattern (Deprecated)

New Pattern

from tortoise import connections

from tortoise.connection import get_connections

connections.get("alias")

Tortoise.get_connection("alias")

connections.all()

get_connections().all()

connections.close_all()

Tortoise.close_connections()