Nag-free PostgreSQL ORM
Project description
Coming Soon: A Python ORM That Treats You Like Its 2026
Alchemy is complex, but Idli is simple.
Have Some Idli
(Doesn't work yet)
$ pip install idli
$ uv add idli
Goals
- Act as a simple data persistence & query layer for simple Python apps (typical CRUD apps).
- Primarily support solo devs and small teams who iterate fast. Not intended for those who need 4 approvals to create a new column.
- Be as declarative as possible.
- Keep your data layer code minimal and elegant.
- Manage as much database administration as possible within the application.
- Handle migrations natively, with least nagging.
- Be framework agnostic.
- Support both
syncandasync. - Be well documented.
What Could It Be Like?
from datetime import datetime
import uuid
from idli import connect
db = connect('postgresql://user:pwd@localhost/somedb')
@db.Model
class Task:
id: uuid.UUID = uuid.uuid7 # initialize with function value
title: str
description: str | None # nullable column because None is an allowed type
status: str = 'todo' # initialize with default value as 'todo'
created: datetime = datetime.now
updated: datetime | None
task = Task(
title = "Ship this ORM",
description = "Before the year ends",
)
task.save()
# tomorrow
task = Task.select(title = "Ship this ORM").one()
task.status = 'doing'
task.save()
# few weeks later
task = Task.select(title = "Ship this ORM").one()
task.update(status = 'done') # using .update will update the status and save it.
# next year
pending_tasks = Task.select(status__neq='done')
for task in pending_tasks:
print(task.title, ',', 'Pending Since:', datetime.now()-task.created)
Migrations
Apart from Django ORM, there is no other Python ORM that I know of that handles database migrations natively. Even with that, I'm too lazy to 'make migrations', check them into my VCS, run them, etc. It's okay be to lazy and prioritize other things in life. Hence, Idli will support auto-migrations for non-destructive migrations. Destructive migrations will have to be done by hand. Suppose the above data model has to be extended a few days later:
from datetime import datetime
import uuid
from idli import connect, PrimaryKey, Index
db = connect(
'postgresql://user:pwd@localhost/somedb',
sambar_dip = True # this will automatically create tables, columns, and indexes defined below
)
@db.Model
class Task:
id: uuid.UUID = uuid.uuid7 # initialize with function value
title: str
description: str | None # nullable column because None is an allowed type
status: str = 'todo' # initialize with default value as 'todo'
created: datetime = datetime.now
updated: datetime | None
owner: User # newly created column referencing another table
__idli__ = [
Index('owner', '-created') # newly created Index
]
@db.Model
class User: # new table
username: str
full_name: str
email: str
send_task_reminders: bool = False
__idli__ = [
PrimaryKey('username')
]
This is inspired from GORM for Golang:
NOTE: AutoMigrate will create tables, missing foreign keys, constraints, columns and indexes. It will change existing column’s type if its size, precision changed, or if it’s changing from non-nullable to nullable. It WON’T delete unused columns to protect your data. - (from GORM docs: https://gorm.io/docs/migration.html)
Async
import asyncio
from datetime import datetime
import uuid
from idli import async_connect
db = async_connect('postgresql://user:pwd@localhost/somedb')
@db.Model
class Task:
id: uuid.UUID = uuid.uuid7 # initialize with function value
title: str
description: str | None # nullable column because None is an allowed type
status: str = 'todo' # initialize with default value as 'todo'
created: datetime = datetime.now
updated: datetime | None
async def main():
task = Task(
title = "Ship this ORM",
description = "Before the year ends",
)
await task.save()
asyncio.run(main())
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file idli-0.2.0.tar.gz.
File metadata
- Download URL: idli-0.2.0.tar.gz
- Upload date:
- Size: 28.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2be2fd8e9279c9631c087803a8932c6a5a43abfa2f49f53bc4e5477bfdcd7e7
|
|
| MD5 |
fa5291c11a6c790ae0b896eb9ca73028
|
|
| BLAKE2b-256 |
141577d49ffc57a84bbeb58f8129daecddd47371e6ce7e9fe09cf919681a1633
|
File details
Details for the file idli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: idli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02240cc683a6e766e5d6bbd3a3001f2867025ba1aabd8eae36727a0500abcf26
|
|
| MD5 |
dd25156ea129346807c808c3513cd68c
|
|
| BLAKE2b-256 |
b42b5c37758eee0187612ddb67ddc3614946b1267189921fc3c7e0516b498484
|