Skip to main content

Helper class for upserting records to database

Project description

CodeQL Dependabot Updates test codecov Python Version from PEP 621 TOML

Sadel

Sadel is a helper class for upserting records with SQLModel.

Installation

pip install sadel

Example upsert

from sadel import Sadel
from sqlalchemy.ext.asyncio import create_async_engine
from sqlmodel import Field, create_engine, select, or_
from sqlmodel.ext.asyncio.session import AsyncSession

class Hero(Sadel, table=True):
    __tablename__ = "hero" 
    _upsert_index_elements = {"id"}

    id: int | None = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: int | None = None

# Create
sqlite_url_async = "sqlite+aiosqlite:///database.db" 
async_engine = create_async_engine(sqlite_url_async, echo=True, future=True)


hero = Hero(name="Deadpond", secret_name="Dive Wilson")

async with AsyncSession(async_engine) as session:
    # Upsert the record
    await Hero.upsert(hero, session)
    
    # Fetch the upserted record
    result = (
        (await session.exec(select(Hero).where(Hero.name == "Deadpond")))
        .all()
    )

    print(result)

Output:

[Hero(id=1, name='Deadpond', secret_name='Dive Wilson', age=None, created_on=datetime.datetime(2024, 8, 1, 19, 39, 7), modified_on=None)]

Example batch upsert

hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)

async with AsyncSession(async_engine) as session:
    await Hero.batch_upsert([hero_1, hero_2, hero_3], session)
    result = (
        (
            await session.exec(
               select(Hero).where(or_(Hero.name == "Deadpond",  Hero.name == "Spider-Boy", Hero.name == "Rusty-Man"))
            )
        )
        .all()
    )
    print(result)

Output:

[Hero(id=1, name='Deadpond', secret_name='Dive Wilson',age=None, created_on=datetime.datetime(2024, 8, 1, 19, 39, 7), modified_on=None), 
Hero(id=2, name='Spider-Boy", secret_name='Pedro Parqueador',age=None, created_on=datetime.datetime(2024, 8, 1, 19, 39, 7), modified_on=None),
Hero(id=3, name='Rusty-Man', secret_name='Tommy Sharp', age=48, created_on=datetime.datetime(2024, 8, 1, 19, 39, 7), modified_on=None)]

Example update record

async with AsyncSession(async_engine) as session:
    # Upsert the record
    hero = Hero(name="Deadpond", secret_name="Dive Wilson", age=25)
    await Hero.upsert(hero, session)

    # Update the record
    hero.age = 30
    # Upsert the updated record
    await Hero.upsert(hero, session)

    # Fetch the updated record
    result = (
        (await session.exec(select(Hero).where(Hero.name == "Deadpond")))
        .scalars()
        .all()
    )

    print(result)

Output:

[Hero(id=1, name='Deadpond', secret_name='Dive Wilson', age=30, created_on=datetime.datetime(2024, 8, 1, 19, 39, 7), modified_on=datetime.datetime(2024, 8, 1, 19, 39, 8))]

Features

  • Upsert and batch_upsert functions.
  • For auditing, automatically adds and manages created_on and modified_on columns to your table (timezones are supported).
  • Validates your data before upserting using Pydantic validate_model method (not supported in SQLModel)
  • Asyncio
  • Compatible with Alembic
  • Specify the (PK) columns to use for upserting using _upsert_index_elements attribute
  • Ignore specific columns from updating using _upsert_exclude_fields attribute

Contributing

  • Fork the repository
  • Create a new branch
  • Make your changes
  • Raise a PR

License

This project is licensed under the terms of the MIT License

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

sadel-0.1.1.tar.gz (5.1 kB view details)

Uploaded Source

Built Distribution

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

sadel-0.1.1-py3-none-any.whl (4.9 kB view details)

Uploaded Python 3

File details

Details for the file sadel-0.1.1.tar.gz.

File metadata

  • Download URL: sadel-0.1.1.tar.gz
  • Upload date:
  • Size: 5.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sadel-0.1.1.tar.gz
Algorithm Hash digest
SHA256 299c0a9746d91ce10e519213c4e672be8104ce736bed0739212dfbbaead77834
MD5 17a96bfa9fadcf0b35d9a5254485c47c
BLAKE2b-256 c739836811146b6f39150588af783a5a57d7aa9d05eed283b7fc7bffc0c77d77

See more details on using hashes here.

Provenance

The following attestation bundles were made for sadel-0.1.1.tar.gz:

Publisher: build-and-publish.yml on dan1elt0m/sadel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sadel-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: sadel-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 4.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sadel-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b0b10cc3c1e1c6a56a2e438a76c371a5a0dbe08d97e585faf3424c4799f657a8
MD5 44da9fffb637bade084a78f8b60e30e9
BLAKE2b-256 205a0ab31ff12fccec7bd601e3005233e2f679a1330f2b54ca4ef0377d0ad89a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sadel-0.1.1-py3-none-any.whl:

Publisher: build-and-publish.yml on dan1elt0m/sadel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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