Enterprise-grade, database-driven form builder with approval workflows and external data integration
Project description
Django Forms Workflows
Enterprise-grade, database-driven form builder with multi-stage approval workflows, external data integration, and cross-instance sync
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 with four permission tiers, complete audit trails.
- ๐ REST API โ Opt-in Bearer-token API: list forms, fetch field schema, submit (or save draft), poll status. OpenAPI 3.0 schema + Swagger UI included.
- ๐ผ๏ธ Embeddable Forms โ Embed forms on any website via a
<script>tag or<iframe>. Auto-resize, theme/accent color support, postMessage callbacks. WordPress plugin included. - ๐ณ Pluggable Payments โ Collect payments during form submission with a pluggable provider system. Stripe ships built-in; add custom providers via
register_provider(). - ๐ Shared Option Lists โ Define reusable choice lists once, reference from any form field. Update the list and every field reflects the change.
- ๐ Dependent Workflows โ Workflows that start only after all other workflows on the form complete, enabling convergence gates after parallel tracks.
- ๐ 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, signature (draw or type)
- Field ordering with explicit
orderinteger - 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
- Multiple
WorkflowDefinitionrecords can run as parallel approval tracks on the same form - Conditional stages โ each stage can carry
trigger_conditionsJSON; 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_conditionsdon't match (e.g. only trigger a Finance track whenamount > 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_backenabled 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) setsdue_dateon created tasks - Reminder emails (
send_reminder_after_days) and optional auto-approval after expiry (auto_approve_after_days) - Immediate or batched notifications (
immediate/daily/weekly/monthly/form_field_date) - Optional per-stage reassignment, editable submission data during approval, custom approve button labels, hidden approval history, and bulk export / bulk PDF export controls
- Rejection handling with per-stage or global rejection semantics
- Complete audit trail on every approval, rejection, send-back, and status change
- First-class outbound webhooks per workflow with signed async delivery, retry/backoff, and delivery logs
See the Workflow Guide, Visual Workflow Builder, Dynamic Assignees, Send Back for Correction, Notifications, and Workflow Webhooks.
๐ Sub-Workflows
Spawn child workflow instances from a parent submission:
SubWorkflowDefinitionlinks a parent workflow to a child form definitioncount_fieldcontrols how many sub-workflows to create (driven by a form field value)section_labelandlabel_templatecontrol how child instances are presented in the UIdata_prefixslices the parent's form data to populate each child- Triggered
on_submissionoron_approval detachedmode lets child instances complete independently of the parentreject_parent=Truelets a rejected child immediately reject the parent and cancel sibling child instances- 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.
๐ผ๏ธ Embeddable Forms
Embed DFW forms on any external website:
- Single
<script>tag creates a responsive iframe with auto-resize viapostMessage - Configurable theme (
light/dark), accent color, min height - Callbacks:
data-on-submit,data-on-loadfor parent page integration - WordPress plugin included (
[dfw_form]shortcode + Gutenberg block) - Admin embed code panel with copy-to-clipboard snippets
- Inline success state โ no redirects, iframe stays self-contained
See Embedding Guide.
๐ณ Payment Collection
Collect payments as part of the form submission flow:
- Pluggable provider architecture:
PaymentProviderABC, provider registry,PaymentResultdataclass - Two flow types: INLINE (payment form on your site, e.g. Stripe Elements) and REDIRECT (external payment page)
- Built-in Stripe provider using PaymentIntents with automatic payment methods
PaymentRecordmodel tracks full payment lifecycle (pending โ completed/failed/refunded)- Configurable per form: provider, amount (fixed or from field), currency, description template
- Custom providers self-register via
register_provider()inAppConfig.ready()
See Payment System Guide.
๐ Shared Option Lists
Define reusable choice lists shared across forms:
SharedOptionListmodel with name, slug, items (JSON array of strings or value/label objects)shared_option_listFK onFormFieldoverrides inline choices for select, radio, multiselect, checkboxes- Choice resolution priority: database prefill โ shared option list โ inline choices
- Update a list once, every referencing field updates immediately
- Form builder UI with shared list dropdown on choice-based fields
See Shared Option Lists Guide.
๐ Dependent Workflows
Workflows that wait for other workflows to complete before starting:
start_trigger = "on_all_complete"onWorkflowDefinition- Enables convergence patterns: parallel tracks must all finish before a final review step
- Peer-level relationship (not parent/child like sub-workflows)
- Complements sub-workflows โ both can coexist on the same form
See the Dependent Workflows section of the Workflows Guide.
๐งฎ Calculated / Formula Fields
Auto-compute field values from other field inputs:
field_type = "calculated"with aformulatemplate 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
๐ 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": [{...}, ...]}inform_data - Available during initial submission and approval step forms
๐ Configurable Prefill Sources
Populate form fields automatically from reusable PrefillSource records:
- User model โ
user.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 values โ
current_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 via
FORMS_WORKFLOWS_CALLBACKSsetting orregister_handler()API; use short names in the admin instead of full Python paths
๐ 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
.jsonsnapshots - Conflict modes โ
update,skip, ornew_slug FORMS_SYNC_REMOTESsetting โ pre-configure named instances (URL + token)- HTTP endpoints protected by Bearer token for CI/scripted use
๐ Managed File Uploads
FileUploadConfigper form definition (allowed extensions, max size)ManagedFilerecords with approval/rejection/supersede lifecycle- Version tracking with
is_currentflag
๐ 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 โ four permission tiers on
FormDefinition:submit_groupsโ can see and submit the formview_groupsโ prerequisite gate for form accessreviewer_groupsโ read-only view of all submissions and approval historyadmin_groupsโ full administrative view of all submissions
- Group-based approval routing via
WorkflowStage.approval_groups - Complete audit logging (
AuditLogโ who, what, when, IP address) - Public / anonymous forms โ mark any form as
requires_login=Falseand anonymous users can submit it; IP-based rate limiting prevents abuse UserProfileauto-created on first login with LDAP/SSO sync
Quick Start
Installation
pip install django-forms-workflows
Setup
- Add to
INSTALLED_APPS:
INSTALLED_APPS = [
# ...
'crispy_forms',
'crispy_bootstrap5',
'django_forms_workflows',
]
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
- Include URLs and run migrations:
# urls.py
urlpatterns = [
path('forms/', include('django_forms_workflows.urls')),
]
python manage.py migrate django_forms_workflows
- 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",
},
}
# Custom callback handlers โ register by short name instead of full Python paths
# These names can be used in PostSubmissionAction.custom_handler_path
FORMS_WORKFLOWS_CALLBACKS = {
"id_photo_copy": "myapp.handlers.IDPhotoHandler",
"sync_to_erp": "myapp.handlers.ERPSyncHandler",
}
# Context processor โ injects site_name into every template
TEMPLATES = [
{
"OPTIONS": {
"context_processors": [
# ... standard processors ...
"django_forms_workflows.context_processors.forms_workflows",
]
}
}
]
Architecture
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 | โ | โ | โ ๏ธ | โ |
| REST API (Bearer token) | โ | โ | โ | โ |
| Bulk export (Excel / CSV) | โ | โ | โ | โ |
| 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:
openpyxlfor Excel spreadsheet field support (pip install django-forms-workflows[excel]) - Optional:
django-auth-ldapfor 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
- ๐ Documentation
- ๐ฌ Discussions
- ๐ Issue Tracker
Roadmap
See docs/ROADMAP.md for the full prioritized roadmap with rationale and implementation notes.
โ Delivered (through v0.48)
- 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)
- REST API โ Bearer-token authenticated endpoints: list forms, fetch field schema, submit (JSON or multipart, including
?draft=1), poll submission status; OpenAPI 3.0 schema + Swagger UI - Bulk export โ Excel and CSV export of submission data from the approval inbox (
allow_bulk_export/allow_bulk_pdf_exportper workflow) - Four-tier RBAC โ
submit_groups,view_groups,reviewer_groups(read-only submission history),admin_groups(full submission view) with consistent enforcement across all list and detail views - Auto-save with configurable interval; Save Draft bypasses required-field validation without storing browser internals (CSRF token, button names)
- Signature field type (drawn or typed) โ v0.45.0
- Form versioning โ ChangeHistory tracking, sync API snapshots, admin diff viewer action โ v0.45.0
- Advanced reporting dashboard (submission analytics, approval times, bottleneck stages) โ v0.46.0
- Settings-based callback handler registry (
FORMS_WORKFLOWS_CALLBACKS) โ register custom handlers by name instead of hardcoding Python paths in the database โ v0.48.0 - First-class workflow webhooks with HMAC signing, async retry/backoff, admin configuration, delivery logs, cloning, and sync support
๐ง Near-term (next 1โ3 releases)
๐ Planned (medium-term)
Credits
Built with โค๏ธ by the Django community.
Special thanks to:
- Logan Nickerson for his time spent testing and helping with business requirements
- Django Crispy Forms
- Celery
- django-auth-ldap
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_forms_workflows-0.63.9.tar.gz.
File metadata
- Download URL: django_forms_workflows-0.63.9.tar.gz
- Upload date:
- Size: 877.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1eec79387261f0732a19d28756e94f379119382eec12e8cea377df97185c59e
|
|
| MD5 |
d5578f41451d22906a382ea7e10cba1b
|
|
| BLAKE2b-256 |
677e5963d7af5942e6bb85c5cf2d28e8517cc041926b1d1257eafa148f67cf24
|
File details
Details for the file django_forms_workflows-0.63.9-py3-none-any.whl.
File metadata
- Download URL: django_forms_workflows-0.63.9-py3-none-any.whl
- Upload date:
- Size: 962.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd7d24294817fb0254a41db99a0d8b5439fcbacfcec70dbe20f7ca225f5c59b3
|
|
| MD5 |
9ed681518b9edbf4638874f725083c22
|
|
| BLAKE2b-256 |
397c765d35cab6dac846cc43953f4a22549ecac8bca8d2af1fbfc823924c74ed
|