Skip to main content

A unified, multi-engine async ORM for Python (MongoDB, PostgreSQL, MySQL, SQLite)

Project description

TabernacleORM 2.1.2 🐍⚡

The Async, Pydantic-powered ORM for Python.

TabernacleORM is a modern, lightweight, and fully async Object-Relational Mapper (ORM) designed for FastAPI and modern Python applications. It supports PostgreSQL, MySQL, SQLite, and MongoDB with a unified, expressive API.

Features

  • Pydantic V2 Native: Models are Pydantic models. Automatic validation, JSON serialization, and OpenAPI schema generation.
  • Fully Async: Built from the ground up for asyncio. No blocking IO.
  • Unified API: Switch between SQL and NoSQL databases without changing your business logic.
  • Relationships: OneToMany, ManyToMany, ForeignKey with lazy loading.
  • Fluent Query Builder: Write expressive queries like User.filter(User.age > 18).
  • Lifecycle Hooks: before_save, after_create, etc., for powerful automation.
  • Stateless Sessions: Thread-safe and concurrency-safe session management.
  • Read/Write Splitting: Native support for replicas and high availability.

Installation

pip install tabernacleorm
# For specific engines:
pip install tabernacleorm[postgresql]
pip install tabernacleorm[mysql]
pip install tabernacleorm[mongodb]

Quickstart

1. Define your Models

Since Tabernacle models are Pydantic models, defining schemas is intuitive:

from typing import Optional
from tabernacleorm import Model, connect
from tabernacleorm.fields import StringField, IntegerField, ForeignKey, OneToMany

# Connect to DB with auto table creation
connect("sqlite:///:memory:", auto_create=True)

class User(Model):
    name: str = StringField(max_length=50)
    age: int = IntegerField(default=18)
    
    # Relationships
    posts: list["Post"] = OneToMany("Post", back_populates="author_id")

    # Lifecycle Hooks
    async def before_save(self):
        self.name = self.name.capitalize()

class Post(Model):
    title: str = StringField()
    content: str = StringField()
    author_id: int = ForeignKey("User")

2. Create and Query

import asyncio

async def main():
    # Create Tables (Handled by auto_create=True, or use migrations in prod)
    # await User.get_engine().executeRaw(User.get_create_table_sql())

    # Create Records
    user = await User.create(name="alice", age=30)
    await Post.create(title="Hello World", content="My first post", author_id=user.id)

    # Fluent Querying (Async)
    users = await User.filter(User.age > 20).all()
    
    # Eager Loading (New!)
    # Fetch users with their 'posts' in one go
    users_with_posts = await User.filter(User.age > 20).include("posts").all()

    # Lazy Loading (New!)
    my_posts = await user.fetch_related("posts")

    # Complex Filtering
    posts = await Post.filter(Post.title.startswith("Hello")).limit(5).all()

asyncio.run(main())

Documentation

New in 2.1.3: Weighted Load Balancing ⚖️

You can now assign weights to read replicas to distribute traffic according to server capacity.

db = connect(
    engine="postgresql",
    write={"url": "postgresql://master:5432/db"},
    read=[
        # Heavy server gets 70% of traffic
        {"url": "postgresql://huge-replica:5432/db", "weight": 70},
        # Smaller server gets 30%
        {"url": "postgresql://small-replica:5432/db", "weight": 30}
    ]
)

Advanced Features

Transactions

Use the session context manager for safe transactions:

engine = User.get_engine()
async with engine.transaction() as session:
    user = await User.create(name="Bob", age=25)
    # Pass session to save() to participate in transaction
    await Post.create(title="Intro", content="...", author_id=user.id, session=session)

Hooks

Available hooks:

  • before_save / after_save
  • before_create / after_create
  • before_delete / after_delete
class user(Model):
    password: str
    
    async def before_save(self):
        if not self.password.startswith("hash:"):
            self.password = f"hash:{self.password}"

Relationships

Define relationships using OneToMany, ManyToMany, or standard ForeignKey. Use await instance.fetch_related("field_name") to load them efficiently.


Built with ❤️ by the Tabernacle Team.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tabernacleorm-2.1.4.tar.gz (19.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tabernacleorm-2.1.4-py3-none-any.whl (64.8 kB view details)

Uploaded Python 3

File details

Details for the file tabernacleorm-2.1.4.tar.gz.

File metadata

  • Download URL: tabernacleorm-2.1.4.tar.gz
  • Upload date:
  • Size: 19.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for tabernacleorm-2.1.4.tar.gz
Algorithm Hash digest
SHA256 305342ea18bc44152160f5baf6145f31e87f9c0bbf116e3d9e2146f8b9d626e9
MD5 e8c8c4a34c57513c00ad4b44b70c6dae
BLAKE2b-256 0215354cb42b6f207a6671d93eec2ac11155e9cfe1fe3947d37c75c624604ab6

See more details on using hashes here.

File details

Details for the file tabernacleorm-2.1.4-py3-none-any.whl.

File metadata

  • Download URL: tabernacleorm-2.1.4-py3-none-any.whl
  • Upload date:
  • Size: 64.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for tabernacleorm-2.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 29934ab803070d76339c929e75faa054d1019011468c31ea9eb7eaeecd8643d7
MD5 5502f31844ded74147aa4be4b3d9beb9
BLAKE2b-256 be0f55115a68b7ee439da7ff9bb36a210843f89e2e53e56931f3d446cf2efb2c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page