Workflow Model Configuration
Developer guide for the Enezaframework workflow engine. Part of the Workflow series.
Table of Contents
- Overview
- Model Configuration Dict
- Relationships
- Full Schema Reference
- Relationship Type Behavior
- Explicit vs Auto-Discovered vs Empty
- Related Guides
Overview
Each WorkflowTypeRegistry entry maps a workflow name to a list of model configuration dicts. Each dict tells the query builder which model to expose, how to label it, and which related models may be filtered. The same shape is consumed by QueryBuilderMixin.get_allowed_models() and get_model_filters().
Model Configuration Dict
{
'slug': 'purchase_order',
'label': 'Purchase Order',
'app_label': 'purchasing',
'model_name': 'PurchaseOrder',
'relationships': [
{
'field_name': 'vendor',
'label': 'Vendor',
'type': 'fk',
'related_app': 'purchasing',
'related_model': 'Vendor',
},
],
}
| Key | Required | Description |
|---|---|---|
slug |
Yes | Unique identifier for the model, used by the UI/JS and by SaveQueryView to find the selected model. |
label |
Yes | Human-readable display name. |
app_label |
Yes | Django app label, for example purchasing. |
model_name |
Yes | Django model class name, for example PurchaseOrder. |
relationships |
No | Explicit relationship definitions. Omit to auto-discover. |
SaveQueryView resolves the chosen model with next((m for m in allowed_models if m['slug'] == model_slug), None) (enezaworkflowengine/views/querybuilder.py:101), so slug must be unique within a workflow.
Relationships
The relationships list defines which related models are exposed as filter groups.
{
'field_name': 'vendor', # FK/M2M field name on the primary model
'label': 'Vendor', # display label for the relationship group
'type': 'fk', # 'fk' or 'm2m'
'related_app': 'purchasing', # related model's app label
'related_model': 'Vendor', # related model's class name
}
| Field | Description |
|---|---|
field_name |
The FK or M2M field name on the primary model. Also used as the lookup prefix (vendor__). |
label |
Display label for the relationship group. Falls back to a title-cased field_name. |
type |
'fk' for ForeignKey, 'm2m' for ManyToMany. |
related_app |
Django app label of the related model. |
related_model |
Class name of the related model. |
The builder expands each relationship into filter definitions for the related model's fields, using <field_name>__<field> lookups (enezaworkflowengine/views/mixin.py:288-301).
Full Schema Reference
{
# Required
'slug': str,
'label': str,
'app_label': str,
'model_name': str,
# Optional — omit for auto-discovery, use [] to disable
'relationships': [
{
# Required per relationship
'field_name': str,
'label': str,
'type': str, # 'fk' or 'm2m'
'related_app': str,
'related_model': str,
},
],
}
Relationship Type Behavior
type |
Behavior |
|---|---|
'fk' |
ForeignKey — traverses __ lookups to filter fields on the related model. |
'm2m' |
ManyToMany — same __ traversal, joined through the through-table. |
Both are emitted as a lookup_prefix of <field_name>__, so the generated filter IDs are identical in shape.
Explicit vs Auto-Discovered vs Empty
The behavior depends on whether the relationships key is present (enezaworkflowengine/views/mixin.py:284-314):
flowchart TD
CFG["model_config passed to get_model_filters()"] --> HAS{"'relationships' key present?"}
HAS -->|Yes| EXPLICIT["Use the explicit list<br/>even when it is empty []"]
HAS -->|No| AUTO["Auto-discover FK + M2M<br/>from model._meta"]
EXPLICIT --> BUILD["Build 'related' filter groups"]
AUTO --> BUILD| Situation | Use |
|---|---|
| Control which relationships appear, custom labels, limit traversal depth | Explicit list |
Expose every FK/M2M with default verbose_name labels |
Omit the key |
| Model has no relationships to expose, or you want to disable auto-discovery | 'relationships': [] |
Omitting the key and setting
[]are not equivalent. Omission triggers auto-discovery; an empty list suppresses it.