Skip to main content

SQLAlchemy field for signed URLs from private object storage

Project description

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

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

sqlalchemy_signed_url-0.1.0.tar.gz (7.0 kB view details)

Uploaded Source

Built Distribution

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

sqlalchemy_signed_url-0.1.0-py3-none-any.whl (6.5 kB view details)

Uploaded Python 3

File details

Details for the file sqlalchemy_signed_url-0.1.0.tar.gz.

File metadata

  • Download URL: sqlalchemy_signed_url-0.1.0.tar.gz
  • Upload date:
  • Size: 7.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for sqlalchemy_signed_url-0.1.0.tar.gz
Algorithm Hash digest
SHA256 28702d25b12f8b00ec738da0d08fccf8129b3af348e5efebd3bb93618805681c
MD5 58a664fedb66a20f0cfecb49a09aa366
BLAKE2b-256 1f5e38fec5843237bdc0067510ec6e4becf83ae22f844639bddb11cd724e925c

See more details on using hashes here.

File details

Details for the file sqlalchemy_signed_url-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sqlalchemy_signed_url-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 370ce9af8ef503163cc14802ccb232f143129f67e528c78b22db82316a64e017
MD5 ec40afd0474b4490b18dc1280e1cbaf8
BLAKE2b-256 ad90c95b3bf563744a8e8842d8a885754c58215cd1a2cee3c1528b3af84492eb

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