Skip to main content

SQLAlchemy Load Generator

Declare what you need, we optimize the rest.

pypi PyPI Downloads Python Versions

Generate SQLAlchemy query optimization options (selectinload + load_only) from simplified field selection syntax.

Why This Library?

SQLAlchemy's query options (selectinload, joinedload, load_only) are powerful but painful to write, especially with nested relationships.

The Problem

1. Verbose nested syntax

# Loading User -> Posts -> Comments requires deep nesting
stmt = select(User).options(
    selectinload(User.posts).options(
        load_only(Post.id, Post.title),
        selectinload(Post.comments).options(
            load_only(Comment.id, Comment.content)
        )
    )
)

2. Coupled with query logic

You must decide what to load at query time, mixing data requirements with query construction. Different API endpoints need different loading strategies, leading to duplicated query code.

3. Dynamic composition is awkward

# Conditionally adding options requires extra logic
options = []
if need_posts:
    options.append(selectinload(User.posts))
if need_comments:
    options.append(selectinload(User.posts).selectinload(Post.comments))
stmt = select(User).options(*options)

4. Easy to cause N+1 or over-fetching

  • Forget selectinload → N+1 queries
  • Load unnecessary fields → wasted memory

The Solution

This library provides a declarative syntax similar to GraphQL:

# Before: verbose, nested, error-prone
stmt = select(User).options(
    selectinload(User.posts).options(
        load_only(Post.id, Post.title),
        selectinload(Post.comments).options(
            load_only(Comment.id, Comment.content)
        )
    )
)

# After: clean, declarative, optimized
generator = LoadGenerator(Base)
options = generator.generate(User, "{ id name posts { title comments { content } } }")
stmt = select(User).options(*options)

Installation

pip install sqlalchemy-load

Requires Python 3.10+

Usage

from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy_load import LoadGenerator

# Initialize with your DeclarativeBase
generator = LoadGenerator(Base)

# Generate options using simplified syntax
options = generator.generate(User, "{ id name posts { title comments { content } } }")

# Use with SQLAlchemy query
stmt = select(User).options(*options)

Syntax

The simplified syntax is similar to GraphQL but without commas:

{ field1 field2 relationship { nested_field } }
  • Fields are space-separated
  • Relationships use { } for nested selection
  • Commas are optional and ignored

Examples

# Simple fields
generator.generate(User, "{ id name email }")

# Nested relationships
generator.generate(User, "{ id posts { title content } }")

# Deeply nested
generator.generate(User, "{ id posts { title comments { content author } } }")

# Multiple relationships
generator.generate(User, "{ name posts { title } profile { bio } }")

# Different models with same generator
generator.generate(Post, "{ title content author { name } }")
generator.generate(Comment, "{ content post { title } }")

API

LoadGenerator(base_class)

Create a generator with a SQLAlchemy DeclarativeBase. Preloads metadata for all models in the registry for optimal performance.

from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass

generator = LoadGenerator(Base)

generator.generate(model_class, query_string) -> list

Generate SQLAlchemy options from a query string.

options = generator.generate(User, "{ id name posts { title } }")
stmt = select(User).options(*options)

Features

  • Preloaded metadata: All model metadata is cached at initialization for fast lookups
  • Result caching: Same query returns cached result, avoiding redundant computation
  • Parse caching: Query string parsing is cached with lru_cache
  • Automatic primary key inclusion: Primary keys are always included in load_only
  • Relationship detection: Automatically detects SQLAlchemy relationships
  • Nested loading: Recursively generates selectinload with nested load_only
  • Error handling: Clear errors for invalid fields, relationships, or syntax

Error Handling

from sqlalchemy_load import (
    LoadGenerator,
    ParseError,
    FieldNotFoundError,
    RelationshipNotFoundError,
)

generator = LoadGenerator(Base)

# Syntax error
try:
    generator.generate(User, "{ id name")  # Missing closing brace
except ParseError as e:
    print(f"Syntax error: {e}")

# Field doesn't exist
try:
    generator.generate(User, "{ nonexistent }")
except FieldNotFoundError as e:
    print(f"Field not found: {e}")

# Relationship doesn't exist
try:
    generator.generate(User, "{ notarelationship { id } }")
except RelationshipNotFoundError as e:
    print(f"Relationship not found: {e}")

Requirements

  • Python >= 3.10
  • SQLAlchemy >= 2.0

License

MIT

Metadata

Release files for sqlalchemy-load 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqlalchemy-load 0.3.1
File Size Uploaded
sqlalchemy_load-0.3.1.tar.gz 42.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlalchemy-load 0.3.1
File Interpreter ABI Platform
sqlalchemy_load-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 49.7 kB

Release files / sqlalchemy_load-0.3.1.tar.gz

Download URL sqlalchemy_load-0.3.1.tar.gz
Size 42.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ee11885b143aa1410115583b155ded894e182171ffef646f57729646e6af905d
BLAKE2b-256 checksum
How to use checksums
61853e5b3f1d4c1c35d975c4a728ddf127186ad3e4928e80bae9ba56e5e4e0ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Release files / sqlalchemy_load-0.3.1-py3-none-any.whl

Download URL sqlalchemy_load-0.3.1-py3-none-any.whl
Size 7.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
689ef741e7c7800bdbf90e78f08e149415149ebf24de06804850f05f333103e5
BLAKE2b-256 checksum
How to use checksums
ddbe58e4037aaef8e7a4f1b1ef852df63926e590aa1dc5b0b822a2333298db15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page