ObjDataModel is the standardised way to define, create, and
interact with data_* and list_* tables in Axion. Instead of
writing a custom Python class per entity, you define a YAML schema
once and get CRUD, validation, pagination, and soft-delete for free.
ObjDataModelEdit is the lifecycle layer on top. It loads a model
YAML into the database (creates tables, seeds reference data,
registers ownership), exports live DB state back to YAML (for
version control), syncs schema drift (adds missing columns), and
diffs before writing.
Old Axion modules (Prism/Meridian era) have their table definitions
scattered across ad-hoc Python code — sql_execute("CREATE TABLE IF NOT EXISTS ...") buried inside __init__ methods, seed data in
undocumented SQL scripts, no record of which module owns which
table.
ObjDataModel gives each module a single YAML file that declares
its entire data layer:
| Section | What It Declares |
|---|---|
description: |
What the module is for |
models: |
Table schemas (columns, types, PKs, validation) |
database.schema: |
CREATE TABLE SQL for fresh deploys |
data: |
Checksummed seed/reference rows |
| Table | PK | Purpose |
|---|---|---|
def_datamodel |
(Package, DataModel) | Registry — Description, Version, VersionDate |
def_datamodel_tables |
(Package, DataModel, TableName) | Junction — many-to-many ownership |
The DataModel column on def_formflow, def_workflow, and
def_service links each module to its data model.
| Step | Command / Action |
|---|---|
| 1. Introspect | save_model auto-generates YAML from live tables |
| 2. Clean up | Add descriptions, fix types, add seed data |
| 3. Commit | resource.datamodels/package.<pkg>/<model>.yaml |
| 4. Deploy | load_model recreates everything from YAML |
| 5. Evolve | sync_schema adds missing columns without data loss |
| Operation | Direction | What It Does |
|---|---|---|
load_model |
YAML → DB | Create tables + register + seed + bump version |
save_model |
DB → YAML | Introspect schemas + dump rows with checksums |
sync_schema |
YAML → DB | ALTER TABLE ADD COLUMN for missing fields |
diff_model |
Read-only | Compare YAML vs live without writing |
validate_yaml |
Read-only | Structure check before any DB writes |
load_data / save_data |
Either | Row data only, no schema changes |
load_all / save_all |
Either | Batch: every model in a package |
Files live in resource.datamodels/package.<pkg>/:
resource.datamodels/
package.homechoice/
gaming_journey.yaml
package.fullhouse/
credit_journey.yaml
Path resolution: package → archetype → root fallback.
description: >
Brief explanation of what this model is for.
models:
my_lookup:
table: data_my_lookup
guid_field: Id
fields:
Id:
type: int
primary_key: true
required: true
Name:
type: varchar(100)
required: true
Active:
type: char(1)
default: "Y"
database:
schema:
data_my_lookup: |
CREATE TABLE `data_my_lookup` (
`Id` int NOT NULL,
`Name` varchar(100) NOT NULL,
`Active` char(1) DEFAULT 'Y',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE={collation}
data:
data_my_lookup:
rows:
- Id: 1
Name: "First Item"
- Id: 2
Name: "Second Item"
checksum: abc123def456...
| Option | Type | Purpose |
|---|---|---|
type |
string | SQL column type |
primary_key |
bool | Column is PK |
required |
bool | NOT NULL |
default |
any | SQL DEFAULT value |
auto_now |
bool | Set to NOW() on save |
enum |
list | Allowed values (validation) |
max_length |
int | Max string length |
min / max |
number | Numeric bounds |
data_* — runtime / transactional datalist_* — lookup / reference lists (read-mostly)# Load a model (create tables + register + seed)
python factory.core/ObjDataModelEdit.py load gaming_journey \
--package HOMECHOICE
# Export current DB state to YAML
python factory.core/ObjDataModelEdit.py save gaming_journey \
--package HOMECHOICE
# Schema only (no row data)
python factory.core/ObjDataModelEdit.py save gaming_journey \
--no-data
# Sync schema: add missing columns
python factory.core/ObjDataModelEdit.py sync gaming_journey
# Dry-run comparison
python factory.core/ObjDataModelEdit.py diff gaming_journey
# Validate YAML structure
python factory.core/ObjDataModelEdit.py validate gaming_journey
# List all registered models
python factory.core/ObjDataModelEdit.py list
# Batch: load/save all models for a package
python factory.core/ObjDataModelEdit.py load-all \
--package HOMECHOICE
python factory.core/ObjDataModelEdit.py save-all \
--package HOMECHOICE
# Remove a model from registry (keeps tables)
python factory.core/ObjDataModelEdit.py delete gaming_journey
from ObjDataModelEdit import ObjDataModelEdit
edit = ObjDataModelEdit(DB=self.DB)
# Load
result = edit.load_model('gaming_journey', 'HOMECHOICE')
# Save
path = edit.save_model('gaming_journey', 'HOMECHOICE')
# Sync schema
changes = edit.sync_schema('gaming_journey', 'HOMECHOICE')
# Diff (dry run)
diff = edit.diff_model('gaming_journey', 'HOMECHOICE')
# Auto-resolve from def_formflow
result = edit.load_model_for_formflow('SW_JOURNEY')
# Query
models = edit.list_models('HOMECHOICE')
refs = edit.get_models_for_table('data_games_exceptions')
desc = edit.get_description('gaming_journey', 'HOMECHOICE')
# Lifecycle
edit.unregister_table('gaming_journey', 'old_table')
edit.delete_model('gaming_journey', 'HOMECHOICE')
The Helix Resorts gaming journey model defines 6 tables:
| Table | Purpose |
|---|---|
data_games_intensity |
Competitive tier (Bronze → Diamond) |
data_games_snack |
Snack bar loadout |
data_games_spin_discount |
Spin wheel segments |
data_games_exceptions |
Gaming sessions + dietary prefs |
data_games_interests |
Nerd interest categories |
data_games_preferences |
Schedule preferences |
Located at
resource.datamodels/package.homechoice/gaming_journey.yaml,
linked via def_formflow.DataModel = 'gaming_journey' on
SW_JOURNEY.
| File | Purpose |
|---|---|
factory.core/ObjDataModel.py |
Runtime CRUD class |
factory.core/ObjDataModel.md |
Full API documentation |
factory.core/ObjDataModelEdit.py |
Lifecycle manager |
factory.core/ObjDataModelEdit.md |
Full API documentation |
factory.core/ObjDataModelEdit.yaml |
Schema for def_datamodel* tables |
resource.datamodels/ |
YAML file root |