Skip to main content

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.

Release Stars Issues Contributors

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nexorm-0.2.0.tar.gz (29.1 kB view details)

Uploaded Source

Built Distribution

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

nexorm-0.2.0-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

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

Hashes for nexorm-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8ee0d3b867f16f56ed5743c974a73d9581ffc89257efcea15d0330d2fc6869bf
MD5 f26a22891a21a149e301b4550523fa8f
BLAKE2b-256 2b3049412aab6a1f268d0374b74d247336472a161924ac0a33fe06df0e06b7a9

See more details on using hashes here.

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

Hashes for nexorm-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c77c1b9eeba0ddda45f7b95e27d6e3a06711e28b80c0ebd81c4140e338f7d29b
MD5 62a7f2b034118b01cc04ef022b0436ec
BLAKE2b-256 24404c43661c09b3c6fd9c166e28a511914a0ba53206af5022c5065f660ab0cf

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