A minimal Django-style ORM for SQLite, PostgreSQL, and MySQL applications.
Project description
NexORM
A minimal Python ORM for SQLite, PostgreSQL, and MySQL apps with models, query helpers, transactions, migrations, and named database connections.
Installation
pip install nexorm
SQLite works with Python's standard library. Install the optional driver extras for PostgreSQL or MySQL:
pip install "nexorm[postgres]"
pip install "nexorm[mysql]"
pip install "nexorm[all]"
For local development:
python -m pip install -e ".[dev,all]"
Quick Start
Initialize NexORM in your project:
nexorm init
This creates a local manage.py file and a migrations/ directory:
manage.py
migrations/
After that, you can use NexORM through python manage.py, similar to Django.
Define models in your app, for example app/models.py:
from nexorm import ForeignKey, Model, StringField
class User(Model):
username = StringField(max_length=100, unique=True, index=True)
class Meta:
table_name = "users"
class Post(Model):
title = StringField(max_length=200)
user_id = ForeignKey("User", on_delete="CASCADE", related_name="posts")
class Meta:
table_name = "posts"
Generate and apply migrations:
python manage.py makemigrations
python manage.py migrate
python manage.py showmigrations
python manage.py rollback
python manage.py sqlmigrate 0001_create_table_users.py
By default, manage.py uses db.sqlite3 and imports models from app.models.
You can override both:
python manage.py --database local.sqlite3 --models myproject.models makemigrations
python manage.py --database local.sqlite3 --models myproject.models migrate
Use another backend by passing connection options or a database URL:
python manage.py --backend postgresql --database appdb --host localhost --user app --password secret migrate
python manage.py --backend mysql --database appdb --host localhost --user app --password secret migrate
python manage.py --url postgresql://app:secret@localhost:5432/appdb migrate
python manage.py --url mysql://app:secret@localhost:3306/appdb migrate
Use the ORM:
from nexorm import configure, transaction
from app.models import Post, User
configure("db.sqlite3")
# configure("postgresql://app:secret@localhost:5432/appdb")
# configure("mysql://app:secret@localhost:3306/appdb")
user = User.objects.create(username="admin")
post = Post.objects.create(title="Hello", user_id=user.id)
same_user = User.objects.filter(username__contains="adm").first()
recent_posts = user.posts.order_by("-id").limit(10).all()
with transaction.atomic():
User.objects.create(username="vicky")
Use raw SQL only with parameters:
user = User.objects.raw("SELECT * FROM users WHERE id = ?", [1]).first()
Use the placeholder style for the configured backend: ? for SQLite and %s for PostgreSQL/MySQL.
Use with Flask:
from flask import Flask
from nexorm import configure
def create_app():
configure("db.sqlite3")
app = Flask(__name__)
return app
Models
Define models by subclassing Model and assigning field instances. If a model does not define a primary key, NexORM adds an id field automatically using UUIDv7 values.
from nexorm import BooleanField, DateTimeField, IntegerField, Model, StringField
class Article(Model):
title = StringField(max_length=180)
views = IntegerField(default=0)
published = BooleanField(default=False)
created_at = DateTimeField(nullable=True)
You can still define your own primary key explicitly if a table needs a different ID strategy.
Queries
Post.objects.create(title="First post", user_id=1)
posts = Post.objects.filter(title__contains="First").order_by("-id").limit(10).all()
count = Post.objects.filter(user_id=1).count()
exists = Post.objects.filter(title="First post").exists()
Supported lookup suffixes include exact matching and common comparisons such as gt, gte, lt, lte, contains, startswith, endswith, and in.
Multiple Databases
Configure the default connection:
from nexorm import configure
configure("db.sqlite3")
# or:
configure("postgresql://app:secret@localhost:5432/appdb")
# or:
configure(backend="mysql", database="appdb", host="localhost", user="app", password="secret")
Configure named connections:
from nexorm import configure, transaction
from app.models import User
configure("db.sqlite3")
configure("postgresql://app:secret@localhost:5432/appdb", alias="primary")
configure("mysql://app:secret@localhost:3306/analytics", alias="analytics")
admin = User.objects.using("primary").create(username="admin")
report_user = User.objects.using("analytics").create(username="report")
analytics_users = User.objects.using("analytics").filter(username__contains="rep").all()
with transaction.atomic("analytics"):
User.objects.using("analytics").create(username="worker")
You can also pass a Database instance directly to using(...) or transaction.atomic(...).
Transactions
from nexorm import transaction
with transaction.atomic():
Post.objects.create(title="Inside a transaction", user_id=1)
Nested transactions use database savepoints.
Migrations CLI
Initialize a project:
nexorm init
That command creates this local manage.py file:
from nexorm.cli import main
if __name__ == "__main__":
main()
Generate and apply migrations:
python manage.py makemigrations
python manage.py migrate
python manage.py showmigrations
Other commands:
python manage.py rollback
python manage.py sqlmigrate 0001_initial.py
python manage.py dbshell
You can still use the installed nexorm command directly:
nexorm --database app.sqlite3 --models app.models makemigrations
nexorm --database app.sqlite3 --models app.models migrate
nexorm --backend postgresql --database appdb --host localhost --user app --password secret migrate
nexorm --url mysql://app:secret@localhost:3306/appdb migrate
Build
python -m pip install -e ".[dev,all]"
python -m pytest -q
python -m build
python -m twine check dist/nexorm-0.2.0*
Run PostgreSQL/MySQL integration tests by providing live test database URLs:
NEXORM_POSTGRES_URL="postgresql://nexorm:nexorm@127.0.0.1:55432/nexorm" \
NEXORM_MYSQL_URL="mysql://nexorm:nexorm@127.0.0.1:53306/nexorm" \
python -m pytest -q tests/test_backends.py
Publish to PyPI
Create an API token in PyPI, then upload manually:
python -m twine upload dist/nexorm-0.2.0*
When prompted:
username: __token__
password: pypi-...
Use TestPyPI first if you want a dry run:
python -m twine upload --repository testpypi dist/*
Status
NexORM is an early package. Version 0.2.0 expands the project from SQLite-only usage to SQLite, PostgreSQL, and MySQL support across connections, queries, transactions, relations, migrations, and backend-specific DDL rendering.
Current capabilities include model fields, automatic UUIDv7 primary keys, managers/querysets, parameterized raw queries, transactions with savepoints, named connections, backend-aware relations, and file-based migrations. PostgreSQL and MySQL support is covered by optional Docker-backed integration tests, but the package should still be treated as alpha software while the backend surface matures.
Project details
Release history Release notifications | RSS feed
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 nexorm-0.2.0.tar.gz.
File metadata
- Download URL: nexorm-0.2.0.tar.gz
- Upload date:
- Size: 29.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ee0d3b867f16f56ed5743c974a73d9581ffc89257efcea15d0330d2fc6869bf
|
|
| MD5 |
f26a22891a21a149e301b4550523fa8f
|
|
| BLAKE2b-256 |
2b3049412aab6a1f268d0374b74d247336472a161924ac0a33fe06df0e06b7a9
|
File details
Details for the file nexorm-0.2.0-py3-none-any.whl.
File metadata
- Download URL: nexorm-0.2.0-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c77c1b9eeba0ddda45f7b95e27d6e3a06711e28b80c0ebd81c4140e338f7d29b
|
|
| MD5 |
62a7f2b034118b01cc04ef022b0436ec
|
|
| BLAKE2b-256 |
24404c43661c09b3c6fd9c166e28a511914a0ba53206af5022c5065f660ab0cf
|