django-forms-workflows now supports much more than a single approver list. A form can have multiple workflow tracks, each track can have staged or parallel approvals, and each stage can carry its own routing, UI, and notification behavior.
| Model | Purpose |
|---|---|
WorkflowDefinition |
One approval track attached to a form. A form can have more than one. |
WorkflowStage |
A stage inside a workflow track. Stages with the same order run in parallel. |
StageApprovalGroup |
Through model that orders groups when a stage uses sequence logic. |
ApprovalTask |
The runtime approval task assigned to a user or group. |
NotificationRule |
Event-driven email rules for workflow and stage events. |
WebhookEndpoint |
Event-driven outbound webhooks for workflow lifecycle events. |
- When a form is submitted, the engine loads all
WorkflowDefinitionrows for that form. - Workflows with
start_trigger = "on_submission"(the default) whosetrigger_conditionsmatch the submission start in parallel. - Workflows with
start_trigger = "on_all_complete"are deferred — they don't start yet. - Within each active workflow track, the engine activates the lowest
orderstage(s). - Stages sharing the same
ordervalue run in parallel. - Each stage resolves according to its own
approval_logic:all— every task in the stage must approveany— the first approval winssequence— groups are activated one at a time usingStageApprovalGroup.position
- When all
on_submissionworkflow tracks complete, anyon_all_completeworkflows are started. - The submission is only finalized when all workflows (including deferred ones) are complete.
name_labelfor a user-facing track name such as “Finance Approval”start_triggerto control when the workflow starts:on_submission(default) oron_all_complete(see Dependent workflows below)trigger_conditionsto skip entire workflow tracks unless submission data matchesapproval_deadline_daysto place adue_dateon created approval taskssend_reminder_after_daysandauto_approve_after_daysfor deadline handling- Notification cadence:
immediate,daily,weekly,monthly, orform_field_date hide_approval_historyfor privacy-sensitive formscollapse_parallel_stagesfor a cleaner approval-history displayallow_bulk_exportandallow_bulk_pdf_exportfor submission list actions- first-class webhook endpoints for
submission.created,task.created,submission.approved,submission.rejected, andsubmission.returned
- Stage logic with
approval_logic = all | any | sequence - Parallel stages by giving multiple stages the same
order - Group routing through
approval_groups - Manager-first routing with
requires_manager_approval - Conditional stages with
trigger_conditions - Dynamic assignees using
assignee_form_field+assignee_lookup_type - Optional
validate_assignee_groupenforcement for dynamic assignees allow_send_backto make a stage a valid correction targetallow_reassignso current reviewers can hand the task to another eligible userallow_edit_form_dataso reviewers can update the original submission while approvingapprove_labelto rename the Approve button (for example “Complete” or “Sign Off”)
Approval-only form fields are supported too. Tie a FormField to a workflow stage via FormField.workflow_stage to collect approver-only data such as signatures, notes, dates, or confirmation checkboxes during that stage.
Workflow and stage conditions use the same JSON structure:
{
"operator": "AND",
"conditions": [
{"field": "department", "operator": "equals", "value": "Finance"},
{"field": "amount", "operator": "gt", "value": "1000"}
]
}Supported operators are equals, not_equals, gt, lt, gte, lte, contains, and in.
- Create the form and its submit/view/admin groups.
- Create one or more
WorkflowDefinitionrows for the form. - Add
WorkflowStagerows in execution order. - Attach approval groups to each stage.
- Add optional routing features such as dynamic assignees, send-back, reassign, or editable form data.
- Add
NotificationRulerows for submission received, approval request, stage decision, final approval, rejection, or withdrawal. - Add
WebhookEndpointrows if external systems should receive signed workflow-event callbacks. - Add post-submission actions if approvals should update external systems.
The visual workflow builder is great for the common structure:
- workflow-level timing and notification settings
- stage names, order, logic, manager approval, send-back, and approve labels
- post-submission actions
- sub-workflow configuration
Advanced stage options such as dynamic assignees, reassign, editable form data, and detailed notification rules are still best configured in Django Admin after saving the basic flow.
For a builder-specific capability and limitation matrix, see Visual Workflow Builder.
- Stage 1: Manager Review (
all) - Stage 2: Finance Review (
all) - Stage 3: VP Sign-Off (
any)
Give both “Legal Review” and “Finance Review” order = 2. They will open together after stage 1 completes.
Create two WorkflowDefinition rows on the same form, for example:
- “Department Approval”
- “Security Review”
The submission stays pending_approval until both tracks complete.
Set:
assignee_form_field = manager_emailassignee_lookup_type = email
If the lookup succeeds, the engine creates one personal task for that user instead of group tasks.
The start_trigger field on WorkflowDefinition controls when a workflow starts:
| Value | Behavior |
|---|---|
on_submission (default) |
Starts immediately when the form is submitted |
on_all_complete |
Starts only after every on_submission workflow on the form has completed |
This enables a "gate" pattern where parallel tracks must all finish before a final review step:
| Workflow | start_trigger |
Stages |
|---|---|---|
| Agency Confirmation | on_submission |
Stage 1: Confirmation sent → Stage 2: Confirmation received |
| Preceptor Confirmation | on_submission |
Stage 1: Confirmation sent → Stage 2: Confirmation received |
| Final Approval | on_all_complete |
Stage 1: Approve site, preceptor, unit, dates |
The Agency and Preceptor workflows run in parallel. The Final Approval workflow only starts after both have fully completed. The submission is finalized only when the Final Approval workflow also finishes.
| Feature | Dependent workflows (on_all_complete) |
Sub-workflows (SubWorkflowDefinition) |
|---|---|---|
| Relationship | Peer-level workflows on the same form | Parent → child (one parent workflow owns the children) |
| Trigger | All other workflows complete | Single parent workflow completes (or on submission) |
| Instance count | Always one | Dynamic (N instances from a count_field) |
| Use case | Convergence gate after parallel tracks | Repeated approval flows (e.g. payment installments) |
Both mechanisms can coexist on the same form.