Skip to content

opensensor/django-forms-workflows

Repository files navigation

Django Forms Workflows

Enterprise-grade, database-driven form builder with multi-stage approval workflows, external data integration, and cross-instance sync

License: LGPL v3 Python Version Django Version Version

Overview

Django Forms Workflows bridges the gap between simple form libraries (like Crispy Forms) and expensive SaaS solutions (like JotForm, Formstack). It provides:

  • 📝 Database-Driven Forms — Define forms in the database, not code. 25+ field types including calculated/formula fields and spreadsheet uploads.
  • 🔄 Multi-Stage Approval Workflows — Sequential, parallel, or hybrid approval flows with configurable stages and conditional trigger logic.
  • ↩️ Send Back for Correction — Approvers can return a submission to any prior stage without terminating the workflow.
  • 🎯 Dynamic Assignees — Resolve individual approvers at submit time from form field values (email, username, full name, or LDAP lookup).
  • 🔀 Sub-Workflows — Spawn child workflows from a parent submission (e.g. one form creates N payment approvals).
  • 🔌 External Data Integration — Prefill fields from LDAP, databases, REST APIs, or the Django user model.
  • Post-Submission Actions — Trigger emails, database writes, LDAP updates, or custom Python handlers on submit/approve/reject.
  • 🔄 Cross-Instance Sync — Push/pull form definitions between environments directly from the Django Admin.
  • 🔒 Enterprise Security — LDAP/AD & SSO authentication, RBAC, complete audit trails.
  • 📁 Managed File Uploads — File uploads with approval, rejection, and version tracking per submission.
  • 🧮 Formula Fields — Calculated fields that compute values live from other field values using a template formula.
  • 🏠 Self-Hosted — No SaaS fees, full data control.

Key Features

🎯 No-Code Form Creation

Business users create and modify forms through Django Admin:

  • 25+ field types: text, email, phone, select, radio, checkbox, checkboxes, multiselect, date, time, datetime, decimal, currency, number, URL, file, multi-file, textarea, hidden, section headers, calculated/formula, spreadsheet upload (CSV/Excel), country picker, US state picker
  • Field ordering with explicit order integer
  • Column-width layout per field: full, half, one-third, one-quarter
  • Validation rules (required, regex, min/max length, min/max value)
  • Conditional field visibility (show_if_field / show_if_value)
  • Custom help text, placeholders, and CSS classes
  • Read-only and pre-filled fields
  • Draft saving with auto-save support

🔄 Multi-Stage Approval Workflows

Flexible approval engine built on WorkflowStage records:

  • Each stage has its own approval groups and logic (any / all / sequence)
  • Stages execute in order; next stage unlocks when the current one completes
  • Conditional stages — each stage can carry trigger_conditions JSON; stages whose conditions don't match the submission data are automatically skipped
  • Workflow-level trigger conditions — entire parallel approval tracks are skipped when their workflow trigger_conditions don't match (e.g. only trigger a Finance track when amount > 10000)
  • Dynamic individual assignees — set assignee_form_field + assignee_lookup_type (email / username / full_name / ldap) on a stage to resolve the approver from a form field value at runtime; falls back to group tasks when the value cannot be resolved
  • Send Back for Correction — approvers can return a submission to any prior stage that has allow_send_back enabled without terminating the workflow; full audit entry recorded
  • Stage-specific form fields (e.g. approver notes, signature date) appear only during that stage
  • Configurable approval deadline (approval_deadline_days) sets due_date on created tasks
  • Email notifications and configurable reminder cadence (daily / weekly / none)
  • Escalation routing when a form field exceeds a threshold (e.g. amount > $5 000)
  • Rejection handling with per-stage or global rejection semantics
  • Complete audit trail on every approval, rejection, send-back, and status change

🔀 Sub-Workflows

Spawn child workflow instances from a parent submission:

  • SubWorkflowDefinition links a parent workflow to a child form definition
  • count_field controls how many sub-workflows to create (driven by a form field value)
  • data_prefix slices the parent's form data to populate each child
  • Triggered on_approval, on_submit, or manual
  • detached mode lets child instances complete independently of the parent
  • Parent submission status reflects aggregate child completion when not detached
  • Sub-workflows support the same send-back mechanism via handle_sub_workflow_send_back

See Sub-Workflows Guide for a full walkthrough.

🧮 Calculated / Formula Fields

Auto-compute field values from other field inputs:

  • field_type = "calculated" with a formula template string (e.g. {first_name} {last_name})
  • Live client-side evaluation updates the read-only field as the user types
  • Authoritative server-side re-evaluation on submit prevents tampering
  • Available in both regular form submission and approval step forms

See Calculated Fields Guide.

📊 Spreadsheet Upload Fields

Accept CSV or Excel files as structured form input:

  • field_type = "spreadsheet" with accept .csv, .xls, .xlsx
  • Parsed and stored as {"headers": [...], "rows": [{...}, ...]} in form_data
  • Available during initial submission and approval step forms

🔌 Configurable Prefill Sources

Populate form fields automatically from reusable PrefillSource records:

  • User modeluser.email, user.first_name, user.username, etc.
  • LDAP / Active Directory — any LDAP attribute (department, title, manager, custom)
  • External databases — schema/table/column lookup with template support for multi-column composition
  • Custom database queries — reference a named query via database_query_key
  • System valuescurrent_date, current_time

⚡ Post-Submission Actions

Automatically run side-effects after a submission event:

Trigger Description
on_submit Runs immediately on form submission
on_approve Runs when the submission is approved
on_reject Runs when the submission is rejected
on_complete Runs when the entire workflow completes

Action types: email, database, ldap, api, custom

Features:

  • Conditional execution with 10 operators (equals, not_equals, greater_than, less_than, contains, not_contains, is_empty, is_not_empty, is_true, is_false, plus date comparisons)
  • Automatic retries with configurable max_retries
  • Execution ordering for dependent actions
  • Idempotent locking (is_locked) to prevent double-execution
  • Full execution logging via ActionExecutionLog
  • Pluggable handler architecture — register custom handlers for new action types

🔄 Cross-Instance Form Sync

Move form definitions between environments from the Django Admin:

  • Pull from Remote — connect to a configured remote instance and import selected forms
  • Push to Remote — select forms and push to any destination
  • Import / Export JSON — portable .json snapshots
  • Conflict modesupdate, skip, or new_slug
  • FORMS_SYNC_REMOTES setting — pre-configure named instances (URL + token)
  • HTTP endpoints protected by Bearer token for CI/scripted use

📁 Managed File Uploads

  • FileUploadConfig per form definition (allowed extensions, max size)
  • ManagedFile records with approval/rejection/supersede lifecycle
  • Version tracking with is_current flag

🔒 Enterprise-Ready Security

  • LDAP/Active Directory authentication with auto-sync of profile attributes
  • SSO integration (SAML, OAuth) with attribute mapping to UserProfile
  • Role-based access: submit_groups and view_groups on FormDefinition
  • Group-based approval routing via WorkflowStage.approval_groups
  • Complete audit logging (AuditLog — who, what, when, IP address)
  • UserProfile auto-created on first login with LDAP/SSO sync

Quick Start

Installation

pip install django-forms-workflows

Setup

  1. Add to INSTALLED_APPS:
INSTALLED_APPS = [
    # ...
    'crispy_forms',
    'crispy_bootstrap5',
    'django_forms_workflows',
]

CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
  1. Include URLs and run migrations:
# urls.py
urlpatterns = [
    path('forms/', include('django_forms_workflows.urls')),
]
python manage.py migrate django_forms_workflows
  1. Create your first form in Django Admin!

Optional Settings

FORMS_WORKFLOWS = {
    # Branding — replaces "Django Forms Workflows" across all templates
    "SITE_NAME": "Acme Corp Workflows",

    # LDAP attribute sync on every login
    "LDAP_SYNC": {
        "enabled": True,
        "attributes": {
            "department": "department",
            "title": "title",
            "employee_id": "extensionAttribute1",
        },
    },
}

# Cross-instance form sync
FORMS_SYNC_API_TOKEN = "shared-secret"
FORMS_SYNC_REMOTES = {
    "production": {
        "url": "https://prod.example.com/forms-sync/",
        "token": "prod-token",
    },
}

# Context processor — injects site_name into every template
TEMPLATES = [
    {
        "OPTIONS": {
            "context_processors": [
                # ... standard processors ...
                "django_forms_workflows.context_processors.forms_workflows",
            ]
        }
    }
]

## Architecture

```mermaid
graph TB
    subgraph UI["User Interface"]
        FB["Form Builder<br/>(Admin)"]
        FV["Form Viewer<br/>(End User)"]
        AU["Approval UI<br/>(Approvers)"]
    end

    subgraph Core["Django Forms Workflows"]
        FD["FormDefinition<br/>+ FormField"]
        WF["WorkflowDefinition<br/>+ WorkflowStage"]
        PS["PrefillSource"]
        PA["PostSubmissionAction<br/>+ Executor"]
        SYNC["Sync API<br/>(Push/Pull)"]
    end

    subgraph External["External Systems"]
        AD["LDAP / AD"]
        DB["External<br/>Databases"]
        API["REST APIs"]
        SSO["SSO<br/>(SAML/OAuth)"]
    end

    FB --> FD
    FV --> FD
    AU --> WF
    FD --> PS
    FD --> PA
    FD --> SYNC
    PS --> AD
    PS --> DB
    PA --> DB
    PA --> AD
    PA --> API
    SSO --> Core

Use Cases

  • HR — Onboarding, time-off requests, expense reports, status changes
  • IT — Access requests, equipment requests, change management
  • Finance — Purchase orders, invoice approvals, budget requests
  • Education — Student applications, course registrations, facility booking
  • Healthcare — Patient intake, referrals, insurance claims
  • Government — Permit applications, FOIA requests, citizen services

Comparison

Feature Django Forms Workflows Crispy Forms FormStack Django-Formtools
Database-driven forms
No-code form creation
Self-hosted
Multi-stage approval workflows ⚠️
Sub-workflows
Post-submission actions ⚠️
External data prefill ⚠️
Cross-instance sync
LDAP/AD + SSO integration
Managed file uploads
Audit trail
Open source

Requirements

  • Python 3.10+
  • Django 5.2+
  • PostgreSQL, MySQL, or SQLite (PostgreSQL recommended for production)
  • Optional: Celery 5.0+ with Redis/Valkey for background task processing
  • Optional: openpyxl for Excel spreadsheet field support (pip install django-forms-workflows[excel])
  • Optional: django-auth-ldap for LDAP/AD integration (pip install django-forms-workflows[ldap])
  • Optional: WeasyPrint for PDF export (pip install django-forms-workflows[pdf])

Testing

cd django-forms-workflows
pip install pytest pytest-django
python -m pytest tests/ -v

The test suite covers models, forms, workflow engine (including dynamic assignees, conditional stages, multi-workflow parallel tracks, sub-workflows), sync API, post-submission action executor, views, signals, conditions, and utilities — 298 tests.

Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

License

GNU Lesser General Public License v3.0 (LGPLv3) — see LICENSE for details.

Support

Roadmap

See docs/ROADMAP.md for the full prioritized roadmap with rationale and implementation notes.

✅ Delivered (v0.35)

  • Database-driven form definitions with 25+ field types
  • Dynamic form rendering with Crispy Forms + Bootstrap 5
  • Multi-stage approval workflows (any/all/sequence logic per stage)
  • Conditional workflow & stage trigger logic
  • Dynamic individual assignee resolution (email / username / full name / LDAP)
  • Send Back for Correction (return to any prior stage without terminating)
  • Sub-workflow support (spawn N child instances from a parent)
  • Calculated / formula fields with live client-side evaluation
  • Spreadsheet upload fields (CSV, XLS, XLSX)
  • LDAP/AD integration with profile sync
  • SSO attribute mapping (SAML/OAuth)
  • Configurable prefill sources (user, LDAP, database, API, system values)
  • Post-submission actions with conditional execution, ordering & retries
  • Cross-instance form sync (push/pull/JSON import-export)
  • Managed file uploads with approval lifecycle and S3/Spaces presigned URLs
  • Conditional field visibility (client-side JS, no page reload)
  • Form templates and cloning
  • Nested category hierarchy with group-based access control
  • WeasyPrint PDF export with multi-column layout
  • Column-picker approval inbox with DataTables
  • Complete audit logging (who, what, when, IP)
  • Configurable site branding via FORMS_WORKFLOWS['SITE_NAME']
  • Comprehensive test suite (298 tests)

🚧 Near-term (next 1–3 releases)

  • REST API for programmatic form submission and status polling
  • Webhook delivery on workflow events (submit / approve / reject)
  • Dashboard analytics (submission counts, approval times, bottleneck stages)

📋 Planned (medium-term)

  • Signature field type (drawn or typed)
  • Form versioning — immutable snapshots with diff viewer
  • Advanced reporting and bulk export (Excel/CSV with field filters)
  • Multi-tenancy support (organisation-scoped form libraries)
  • Plugin / custom handler marketplace

Credits

Built with ❤️ by the Django community.

Special thanks to:

About

An enterprise-grade Django app: database-driven form builder with approval workflows and external data integration. It bridges the gap between simple form libraries (like Crispy Forms) and expensive SaaS solutions (like JotForm, Formstack).

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors