Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sqlalchemy-signed-url

sqlalchemy-signed-url is a small utility library that helps you work with private object storage (S3, GCS, etc.) at the SQLAlchemy field level.

The core idea is simple:

  • Store only object keys in the database
  • Generate signed URLs (presigned URLs) only at read/serialization time
  • Keep upload and write operations explicit and outside the ORM

This library provides a clean, repeatable pattern for doing exactly that.

Motivation

In systems that use private object storage, the following pattern is very common:

  • Files live in a private bucket/container
  • The database stores a full storage URI, not a public-facing URL.
  • Clients receive a short-lived signed URL when data is returned
  • Upload and download logic is handled explicitly in the application layer

In practice, this logic often ends up:

  • Scattered across serializers and service layers, or
  • Reimplemented slightly differently for each model

Over time, this makes consistency and maintenance difficult.

sqlalchemy-signed-url moves this pattern to the model field level, so it can be declared once and reused everywhere.

Example

1. Configure storage (once)

from sqlalchemy_signed_url import ObjectStorage
from sqlalchemy_signed_url.signers.s3 import S3PresignedURLSigner


# Let the signer create its own boto3 client
ObjectStorage.initialize(
    signer=S3PresignedURLSigner(bucket="my-bucket", region_name="us-east-1"),
)

# If you already have a preconfigured boto3 S3 client,
# the signer will use it as-is and ignore region_name.
ObjectStorage.initialize(
    signer=S3PresignedURLSigner(bucket="my-bucket", client=preconfigured_client)
)

2. Declare a model

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy_signed_url import SignedURLField


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    profile_image = SignedURLField(base_path="users/profile")

3. Save (assign raw key)

# The field automatically provides:
# - <field>_key        → raw key accessor
# - <field>_location   → (bucket, object_key) for uploading
# - <field>_signed_url → on-demand presigned URL

# Assign a raw key to the model (no upload yet)
user = User(profile_image_key="avatar.png")

# Get upload destination from the model
bucket, key = user.profile_image_location

# Upload the file yourself
s3_client.upload_file("local/path/avatar.png", bucket, key)

# Save the key to the database
session.add(user)
session.commit()

4. Read

user.profile_image
# "s3://my-bucket/users/profile/avatar.png"

user.profile_image_key
# "avatar.png"

user.profile_image_signed_url
# presigned URL

Status

✅ Implemented

  • S3-based presigned URL generation (read-only)
  • Instance-level caching of presigned URLs
    • Cache per ORM instance
    • Invalidate cache when <field>_key changes
  • Allow injecting storage client

🚧 Planned

  • Support additional storage providers

    • Google Cloud Storage (GCS)
    • Microsoft Azure Blob Storage
    • Other S3-compatible storages
  • Presigned URL for uploads

    • Generate upload URLs (e.g. PUT, POST)
    • Separate read/write URL configuration
    • Optional constraints (content-type, max size, etc.)
  • Validate Alembic compatibility

    • Confirm autogenerate behavior with SignedURLField

About

A small utility library that helps you work with private object storage (S3, GCS, etc.) at the SQLAlchemy field level

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages