Workflow Type Registry Quick Start
Developer guide for the Enezaframework workflow engine. Part of the Workflow series.
Table of Contents
- Overview
- Built-in Workflow Types
- Using the Generic Query Builder
- What Happens Without a Workflow Name
- Adding a Project Workflow Type
- Related Guides
Overview
The registry needs no setup for the built-in workflow types. You open the generic query builder with a workflow_name parameter; the framework resolves the allowed models from WorkflowTypeRegistry and renders the filter UI. No custom view is required.
flowchart LR
A["Open /workflow/query-builder/<br/>?workflow_name=ExpenseWorkflow"] --> B["QueryBuilderMixin.get_workflow_name()"]
B --> C["WorkflowTypeRegistry.get_allowed_models()"]
C --> D["Allowed model configs"]
D --> E["Filter definitions + aggregate options"]
E --> F["query_builder.html"]Built-in Workflow Types
Defined in WorkflowTypeRegistry._framework_registry (enezaworkflowengine/services/workflow_type.py:36-99):
| Workflow Name | Primary Model | App |
|---|---|---|
PurchaseOrderWorkflow |
PurchaseOrder |
purchasing |
InvoiceWorkflow |
Frameworktestdocument |
frameworkapp |
CreditCardWorkflow |
CreditCardTransaction |
accounting |
ExpenseWorkflow |
Expense |
accounting |
LeaveApplicationWorkflow |
LeaveApplication |
hr |
Their values must also exist in Workflownames (enezaworkflowengine/models/choices.py:24-29) so they can be selected in the UI and stored on SavedQuery.workflow.
Using the Generic Query Builder
Open the builder with the workflow name:
/workflow/query-builder/?workflow_name=ExpenseWorkflow
The generic views read the registry automatically and:
- resolve the allowed models for the workflow,
- generate filter definitions per model (
get_model_filters), - generate aggregate options per model (
get_aggregate_options), - render the query builder UI,
- save queries with the workflow name attached.
# enezaworkflowengine/views/querybuilder.py:55-76
class BuildQueryView(QueryBuilderMixin, LoginRequiredMixin, TemplateView):
template_name = 'query_builder.html'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
workflow_name = self.get_workflow_name()
allowed_models = self.get_allowed_models()
ctx['models_list'] = allowed_models
ctx['workflow_name'] = workflow_name
filters_by_model = {
m['slug']: self.get_model_filters(m['app_label'], m['model_name'], model_config=m)
for m in allowed_models
}
for m in allowed_models:
filters_by_model[m['slug']]['aggregates'] = self.get_aggregate_options(m)
ctx['filters_by_model_json'] = json.dumps(filters_by_model)
ctx['models_list_json'] = json.dumps(allowed_models)
return ctx
URL naming. The engine is mounted at the
/workflow/path prefix with the URL namespaceenezaworkflowengine(enezaworkflowengine/urls.py:47). Reverse the builder withenezaworkflowengine:build_query, and the save endpoint withenezaworkflowengine:save_query.
What Happens Without a Workflow Name
If no workflow_name is supplied (request parameter or view attribute), get_allowed_models() returns the fallback _default_models (workflow_type.py:104-134, :200-202):
| Slug | Model | App |
|---|---|---|
user |
User |
enezacommon |
entity |
Entity |
enezaframework |
This keeps the builder usable for generic queries. To scope the builder to a workflow, always pass workflow_name.
Adding a Project Workflow Type
A project-defined workflow is three small edits:
- Define
WORKFLOW_TYPE_REGISTRYin theworkflowconfig/type_registry.pysubmodule (or a singleworkflowconfig.py). - Point
MY_PROJECT_WORKFLOWS_CONFIGat that class insettings.py. - Add the workflow value to a
Workflownamessubclass and pointMY_PROJECT_WORKFLOWS_NAMEat it.
# myproject/workflowconfig.py
from enezaworkflowengine.models.choices import Workflownames
class ProjectWorkflowNames(Workflownames):
SALESORDERWORKFLOW = 'SalesOrderWorkflow', 'Sales Order Workflow'
class WorkflowTypeConfig:
WORKFLOW_TYPE_REGISTRY = {
'SalesOrderWorkflow': [
{
'slug': 'sales_order',
'label': 'Sales Order',
'app_label': 'sales',
'model_name': 'SalesOrder',
'relationships': [
{
'field_name': 'customer',
'label': 'Customer',
'type': 'fk',
'related_app': 'crm',
'related_model': 'Customer',
},
],
},
],
}
# myproject/settings.py
MY_PROJECT_WORKFLOWS_NAME = 'myproject.workflowconfig.ProjectWorkflowNames'
MY_PROJECT_WORKFLOWS_CONFIG = 'myproject.workflowconfig.WorkflowTypeConfig'
Full details are in Workflow Project Configuration.