Fields

Field type markers

These are Python 3.12 generic classes that serve as type annotations for entity fields. Sphinx autodoc cannot fully process Python 3.12 class Cls[T]: syntax, so they are described here manually. See Defining Entities for usage examples.

class nextorm.fields.PK[T]

Primary-key field — auto-generated integer by default.

On the class: returns a ColumnExpr for use in query predicates. On an instance: returns the T value.

Example:

class User(Entity):
    id: PK[int]         # auto-increment integer PK
    id: PK[uuid7]       # time-ordered UUID PK
class nextorm.fields.Req[T]

Required (non-nullable) field. Maps to a NOT NULL column.

Example:

class Product(Entity):
    name: Req[str]
class nextorm.fields.Opt[T]

Optional (nullable) field — value may be None. Maps to a nullable column.

Example:

class Product(Entity):
    description: Opt[str]
class nextorm.fields.Local[T]

Local (transient) field — never written to or read from the database. Use it to attach computed or cached state to an entity instance.

Example:

class User(Entity):
    _full_name: Local[str]
    _cache: Local[dict] = Local[dict](default=dict)

Options (passed as Local[T](…)):

  • default: Value or callable returned on Entity() construction

  • py_check: Callable that validates the value on assignment

class nextorm.fields.Set[T]

Collection relation attribute — used for both one-to-many and many-to-many.

Declare Set[Child] on the one side and Single[Parent] on the many side for one-to-many; declare Set[Other] on both entities for many-to-many.

Options (passed as Set[T](…)):

  • table: (M2M only) Override join table name; defaults to {a}_{b} (alphabetical)

  • reverse_column: (M2M only) Override the FK column name to this entity; defaults to {entity_name}_id

  • reverse_columns: (M2M only) Override the composite FK column names; overrides reverse_column

class nextorm.fields.Single[T]

Single-entity relation attribute (FK).

Use Single[Other] for a required FK (NOT NULL, CASCADE). Use Single[Other | None] for an optional FK (NULLABLE, SET NULL). When both sides use Single, a UNIQUE constraint is added (one-to-one).

Options (passed as Single[T](…)):

  • nullable: Override the nullability (defaults to auto-detect from T | None)

  • cascade_delete: True for CASCADE, False for RESTRICT, None (default) for auto-derive from nullable

  • owner: (one-to-one only) True to mark as owning side (has FK), False as non-owning, None (default) for auto-detect

  • fk_name: Custom FK constraint name (defaults to auto-generated fk_…)

  • column: Override the FK column name; defaults to {relation_name}_id

  • columns: Override the composite FK column names; overrides column

Special column types

class nextorm.fields.LongStr[source]

Bases: str

Sentinel type for large text columns.

Maps to LONGTEXT (MariaDB), TEXT (PostgreSQL / SQLite). Use when the content may exceed the ~65 KB limit of a standard MariaDB TEXT column:

class Article(Entity):
    body: Req[LongStr]

By default LongStr fields are lazy — they are omitted from the main SELECT and fetched on first access via a separate query. To load eagerly, pass lazy=False explicitly:

class Article(Entity):
    body: Req[LongStr] = Req(lazy=False)
class nextorm.fields.Json[source]

Bases: object

Sentinel type for JSON columns.

Maps to JSONB (PostgreSQL), JSON (MariaDB), TEXT (SQLite). Values are stored as Python dict / list objects and serialised/deserialised automatically:

class Config(Entity):
    data: Req[Json]
class nextorm.fields.DateTimeTz[source]

Bases: object

Sentinel type for timezone-aware datetime columns.

Maps to TIMESTAMPTZ (PostgreSQL), DATETIME (MariaDB, assumes UTC session), TEXT ISO 8601 (SQLite).

PostgreSQL: psycopg / asyncpg automatically return a timezone-aware datetime object. For MariaDB and SQLite the application is responsible for serialising to/from UTC:

class Event(Entity):
    start_at: Req[DateTimeTz]
class nextorm.fields.Vec[source]

Bases: object

Parameterized sentinel type for fixed-dimension vector columns.

Maps to vector(n) (PostgreSQL with pgvector extension), TEXT (MariaDB / SQLite — JSON-serialised list).

Specify the dimension with positional argument

class Article(Entity):
    embedding: Req[Vec[384]]

Alternatively use Req(dimensions=n) explicitly:

class Article(Entity):
    embedding: Req[Vec] = Req(dimensions=384)

UUID / ULID types

class nextorm.fields.uuid7[source]

Bases: object

Sentinel type for UUID v7 auto-generated primary keys.

Use in entity annotations to declare a time-ordered, sortable UUID PK:

class Event(Entity):
    id: PK[uuid7]

The field is stored as uuid.UUID in Python and mapped to UUID (PostgreSQL), CHAR(36) (MariaDB), or TEXT (SQLite). A UUID v7 value is auto-generated before every INSERT if the field is not already set.

class nextorm.fields.uuid4[source]

Bases: object

Sentinel type for UUID v4 auto-generated primary keys.

Use like PK[uuid4]. Same storage as uuid7 but uses random UUID v4 generation (not time-ordered).

class nextorm.fields.ulid[source]

Bases: object

Sentinel type for ULID auto-generated primary keys.

Use like PK[ulid]. The field is stored as a ULID string (26-character Crockford base32) mapped to CHAR(26) in DDL.

class nextorm.fields.ULID[source]

Bases: str

26-character Crockford base32 ULID value type.

Used as the Python type for PK[ulid] fields. ULID values are stored as CHAR(26) (MariaDB), TEXT (SQLite), or the native UUID column cast to base32 (not supported — stored as TEXT on all backends).

A ULID instance is an ordinary string and sorts lexicographically in creation order (time-order), which is the key property of ULIDs.

Metadata classes

FieldSpec and RelationSpec are the internal dataclasses that hold the resolved field configuration after EntityMeta processes the class body. They are exposed publicly for introspection (e.g. Entity._fields_["name"].spec) but should not be used directly as class-body values — use the marker-call syntax (Req(...), Opt(...), Single(...), etc.) instead.

class nextorm.fields.FieldSpec[source]

Bases: object

Metadata that describes a single persistent column.

EntityMeta creates a FieldSpec automatically for every annotated field. You can set options through the marker call syntax (validated at class-definition time):

class Product(Entity):
    name: Req[str] = Req(max_len=120, unique=True)
    price: Req[float] = Req(min=0.0)
    updated_at: Req[datetime] = Req(volatile=True, sql_default="CURRENT_TIMESTAMP")

Parameters

auto:

True for auto-increment integer PKs or UUID/ULID PKs generated by Python before INSERT. Set automatically by PK; rarely needed manually.

autostrip:

Strip leading/trailing whitespace on every string assignment (default False for LongStr; True for plain str fields when set via StrTypeOpts).

column:

Override the database column name. Defaults to the attribute name.

db_encoding:

Database character encoding for the column, e.g. "utf8mb4" for full Unicode support on MariaDB. Ignored on PostgreSQL and SQLite.

default:

Python-side default value or zero-argument callable. Applied before INSERT when the field was not explicitly set. Use _MISSING (the module-level sentinel) to indicate no default.

dimensions:

Number of dimensions for Vec columns (e.g. 384, 1536). Set automatically when you write Req[Vec[384]].

index:

Create a single-column index on this column.

lazy:

Exclude the column from the main SELECT; load its value on first access via a separate query. Set automatically for LongStr fields.

max:

Inclusive upper bound enforced in Python on every assignment.

max_len:

Maximum string length enforced in Python and reflected in DDL (VARCHAR(n)).

min:

Inclusive lower bound enforced in Python on every assignment.

nullable:

Allow SQL NULL. Set automatically for Opt fields.

precision:

Total significant digits for DECIMAL/NUMERIC columns, or fractional-second precision for DATETIME/TIMESTAMP columns.

primary_key:

Mark this column as (part of) the primary key.

py_check:

Zero-argument callable (value) -> bool; raises ValueError when it returns falsy. Runs on every assignment.

scale:

Digits after the decimal point for DECIMAL/NUMERIC columns.

size:

Integer column bit-width — one of 8, 16, 32, or 64.

sql_default:

Raw SQL expression used in DDL DEFAULT, e.g. "CURRENT_TIMESTAMP". Not applied in Python — use default for that.

sql_type:

Override the inferred SQL type string, e.g. "JSONB" or "GEOMETRY".

unique:

Add a UNIQUE constraint on this column.

unsigned:

Add the UNSIGNED modifier (MariaDB only; ignored on other backends).

uuid_auto:

Python-side UUID/ULID generation strategy: "v7", "v4", or "ulid". Set automatically by the PK marker for UUID/ULID types.

volatile:

Exclude this column from UPDATE statements. Use for columns whose value is maintained entirely by a database trigger or DEFAULT expression.

auto: bool = False
autostrip: bool = False
column: str | None = None
db_encoding: str | None = None
default: Any
dimensions: int | None = None
index: bool = False
lazy: bool = False
max: Any = None
max_len: int | None = None
min: Any = None
nullable: bool = False
precision: int | None = None
primary_key: bool = False
py_check: Callable[[object], bool] | None = None
scale: int | None = None
sql_default: str | None = None
sql_type: str | None = None
size: int | None = None
unique: bool = False
uuid_auto: str | None = None
unsigned: bool = False
volatile: bool = False
property has_default: bool

Return True when a default value or factory has been set.

__init__(auto=False, autostrip=False, column=None, db_encoding=None, default=<factory>, dimensions=None, index=False, lazy=False, max=None, max_len=None, min=None, nullable=False, precision=None, primary_key=False, py_check=None, scale=None, sql_default=None, sql_type=None, size=None, unique=False, uuid_auto=None, unsigned=False, volatile=False)
Parameters:
  • auto (bool)

  • autostrip (bool)

  • column (str | None)

  • db_encoding (str | None)

  • default (Any)

  • dimensions (int | None)

  • index (bool)

  • lazy (bool)

  • max (Any)

  • max_len (int | None)

  • min (Any)

  • nullable (bool)

  • precision (int | None)

  • primary_key (bool)

  • py_check (Callable[[object], bool] | None)

  • scale (int | None)

  • sql_default (str | None)

  • sql_type (str | None)

  • size (int | None)

  • unique (bool)

  • uuid_auto (str | None)

  • unsigned (bool)

  • volatile (bool)

Return type:

None

class nextorm.fields.RelationSpec[source]

Bases: object

Metadata that describes a relation (FK or join-table) column.

EntityMeta creates a RelationSpec automatically from Single and Set annotations.

class Comment(Entity):
    post: Single[Post](fk_name="fk_comment_post", cascade_delete=True)

Note

kind and target are always filled in by EntityMeta from the annotation.

Parameters — Single relations

nullable:

True → NULLABLE FK column with ON DELETE SET NULL. False (default) → NOT NULL column with ON DELETE CASCADE.

cascade_delete:

True — force ON DELETE CASCADE regardless of nullable. False — force ON DELETE RESTRICT regardless of nullable. None (default) — derive automatically from nullable.

column:

Override the FK column name. Defaults to {attr_name}_id.

columns:

Composite FK column names (list). Mutually exclusive with column.

fk_name:

Override the foreign-key constraint name in DDL.

owner:

One-to-one only. True = this side owns the FK column (UNIQUE constraint added here). False = non-owning back-reference. None (default) = auto-detect from nullable or alphabetical order.

primary_key:

True when the FK column is also the table’s primary key. Set automatically by PK when subscripted with an entity type.

Parameters — Set relations

table:

Override the many-to-many join table name.

reverse_column:

Override the join-table column that points back to the declaring entity.

reverse_columns:

Composite version of reverse_column.

Parameters — both kinds

reverse:

Attribute name of the reverse relation on the target entity, used for explicit back-reference wiring when NextORM cannot infer it automatically.

kind: str = ''
target: type[Any] | str | None = None
cascade_delete: bool | None = None
column: str | None = None
columns: list[str] | None = None
fk_name: str | None = None
nullable: bool = False
owner: bool | None = None
primary_key: bool = False
reverse: str | None = None
reverse_column: str | None = None
reverse_columns: list[str] | None = None
table: str | None = None
__init__(kind='', target=None, cascade_delete=None, column=None, columns=None, fk_name=None, nullable=False, owner=None, primary_key=False, reverse=None, reverse_column=None, reverse_columns=None, table=None)
Parameters:
  • kind (str)

  • target (type[Any] | str | None)

  • cascade_delete (bool | None)

  • column (str | None)

  • columns (list[str] | None)

  • fk_name (str | None)

  • nullable (bool)

  • owner (bool | None)

  • primary_key (bool)

  • reverse (str | None)

  • reverse_column (str | None)

  • reverse_columns (list[str] | None)

  • table (str | None)

Return type:

None

class nextorm.fields.LocalSpec[source]

Bases: object

Metadata for a single local (transient) field.

Created by EntityMeta from a Local annotation and stored in cls._locals_. Never reaches the database layer — it exists solely to support Python-side behaviour (defaults and validation) that mirrors what FieldSpec provides for persistent fields.

Parameters

default:

Value or zero-argument callable applied before the first assignment when the field was not supplied to __init__. If omitted, accessing an uninitialised Local field raises AttributeError until the field is assigned — typically inside after_load().

py_check:

Callable (value) -> bool run on every assignment. Raises ValueError when it returns False.

default: Any
py_check: Callable[[object], bool] | None = None
property has_default: bool

Return True when a default value has been set.

__init__(default=<factory>, py_check=None)
Parameters:
  • default (Any)

  • py_check (Callable[[object], bool] | None)

Return type:

None

Composite constraints

nextorm.fields.composite_key(*field_names)[source]

Declare a multi-column unique constraint (equivalent to UNIQUE (a, b)).

Place this inside the entity body as a class attribute:

class Booking(Entity):
    slot: Req[int]
    room: Req[int]
    _ck_slot_room_ = composite_key("slot", "room")
Parameters:

field_names (str)

Return type:

CompositeConstraint

nextorm.fields.composite_index(*field_names)[source]

Declare a multi-column non-unique index (equivalent to INDEX (a, b)).

Place this inside the entity body as a class attribute:

class LogEntry(Entity):
    source: Req[str]
    level: Req[str]
    _idx_source_level_ = composite_index("source", "level")
Parameters:

field_names (str)

Return type:

CompositeConstraint

nextorm.fields.PrimaryKey(*field_names)[source]

Declare a composite primary key spanning two or more fields.

field_names may be scalar field names or relation names (Single relations whose FK column then becomes part of the PK). All referenced relations must be required (non-nullable).

Place this inside the entity body as a class attribute:

class OrderLine(Entity):
    order: Single[Order]
    product: Single[Product]
    quantity: Req[int]
    _pk_ = PrimaryKey("order", "product")


class Enrollment(Entity):
    student_id: Req[int]
    course_id: Req[int]
    grade: Opt[str]
    _pk_ = PrimaryKey("student_id", "course_id")
Parameters:

field_names (str)

Return type:

CompositeConstraint

class nextorm.fields.CompositeConstraint[source]

Bases: object

Multi-column index, unique constraint, or primary key declared at class level.

Do not instantiate directly — use composite_key(), composite_index(), or PrimaryKey() instead.

fields: tuple[str, ...]
unique: bool = False
primary_key: bool = False
__init__(fields, unique=False, primary_key=False)
Parameters:
Return type:

None