Fork from Eric Simorre's django-goflow, updated for modern Python and Django 4/5/6
Project description
Historic links
- https://code.djangoproject.com/wiki/GoFlow:demo
- http://goflow.free.fr/doc/html/install.html#optional-but-useful-modules
This is django-goflow migrated from django 1.X to modern Django versions.
Release 1.1 highlights (2026-02-27):
- Added pluggable scheduler backends (cron/celery).
- Replaced eval/exec in key runtime paths with safe condition parsing.
- Updated automation/admin/designer documentation.
Current compatibility target:
- Django 4.2.x
- Django 5.x
- Django 6.x
- Python 3.9+
Compatibility matrix:
- Python 3.9: Django 4.2
- Python 3.10/3.11: Django 4.2, 5.x
- Python 3.12+: Django 4.2, 5.x, 6.x
Use tox to run compatibility checks across supported Django versions.
Multilingual support:
- Languages: en, fr, zh-hans, zh-hant, ja, de, es, it
- Switching: URL prefix, session/cookie, or browser Accept-Language
Quick start (sampleproject):
-
Create venv and install dependencies.
-
Run migrations:
python sampleproject/manage.py migrate
-
Create a superuser:
python sampleproject/manage.py createsuperuser
-
Run the server:
python sampleproject/manage.py runserver
-
Open:
http://localhost:8000/admin/ http://localhost:8000/workflow/ http://localhost:8000/workflow/designer/<process_id>/
Quick start (leavedemo):
-
Run migrations:
python leavedemo/manage.py migrate
-
Run the server:
python leavedemo/manage.py runserver
-
Open:
http://localhost:8000/leave/admin/ http://localhost:8000/leave/ http://localhost:8000/leave/designer/<process_id>/
Language switching:
-
URL prefix example: /en/leave/ or /zh-hans/leave/
-
POST to /i18n/setlang/ with "language" to set session/cookie
-
To generate translations:
django-admin makemessages -a django-admin compilemessages
Roles and permissions:
- Disable automatic process group creation (use Django auth to manage roles): GOFLOW_AUTO_CREATE_PROCESS_GROUPS = False
Scheduling backends (pluggable):
- Default backend (linux cron + management command): GOFLOW_SCHEDULER_BACKEND = 'goflow.runtime.scheduler.CronSchedulerBackend'
- Optional Celery backend: GOFLOW_SCHEDULER_BACKEND = 'goflow.runtime.scheduler.CelerySchedulerBackend'
Public scheduler interfaces:
schedule_timeout_scan()schedule_workitem_action(workitem_id, action='forward', **kwargs)schedule_notification(user_id, workitem_ids=None)
Cron command:
python manage.py goflow_cron
Transition condition syntax (safe parser):
eq:APPROVEDne:REJECTEDin:APPROVED,OKnotin:REJECTED,CANCELLEDtimeout:3dinstance.condition == 'APPROVED'
Condition strategy:
GOFLOW_CONDITION_STRATEGY = 'compatible'(default): unknown expressions fall back to legacyinstance.condition == raw_text.GOFLOW_CONDITION_STRATEGY = 'strict': unknown/invalid expressions evaluate toFalse.
Condition normalization:
- On transition save, plain values are normalized automatically:
APPROVED->eq:APPROVEDworkitem.time_out(3, unit='days')->timeout:3d
Docs build:
- HTML docs: python -m sphinx -b html -d docs/build/doctrees docs/source docs/build/html
REST API (django-ninja + django-ninja-simple-jwt):
-
Install deps: django-ninja, django-ninja-simple-jwt
-
Generate JWT keys (dev only):
python sampleproject/manage.py make_rsa
-
Auth endpoints: /api/auth/mobile/sign-in /api/auth/mobile/token-refresh /api/auth/web/sign-in /api/auth/web/token-refresh
-
Auth example (web):
curl -X POST http://localhost:8000/api/auth/web/sign-in \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"open"}'
{"access":"<jwt>"}
The refresh token is set in an HttpOnly cookie named refresh.
- Token refresh:
curl -X POST http://localhost:8000/api/auth/web/token-refresh \
--cookie "refresh=<jwt>"
{"access":"<jwt>"}
- Auth example (mobile):
curl -X POST http://localhost:8000/api/auth/mobile/sign-in \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"open"}'
{"access":"<jwt>","refresh":"<jwt>"}
- Protected example:
curl http://localhost:8000/api/protected/me \
-H "Authorization: Bearer <jwt>"
{"username":"admin","is_authenticated":true}
-
Workflow resources (JWT required): /api/protected/processes /api/protected/processes/{process_id}/activities /api/protected/workitems /api/protected/my/workitems /api/protected/workitems/{id}/activate /api/protected/workitems/{id}/complete /api/protected/processes/start
-
List processes:
curl http://localhost:8000/api/protected/processes \
-H "Authorization: Bearer <jwt>"
[{"id":1,"title":"leave","enabled":true}]
- List activities for a process:
curl http://localhost:8000/api/protected/processes/1/activities \
-H "Authorization: Bearer <jwt>"
[{"id":1,"title":"Start","kind":"standard","process_id":1}]
- List all workitems:
curl http://localhost:8000/api/protected/workitems \
-H "Authorization: Bearer <jwt>"
[{"id":1,"status":"active","activity_id":2,"instance_id":1,"user_id":1}]
- List my workitems:
curl http://localhost:8000/api/protected/my/workitems \
-H "Authorization: Bearer <jwt>"
[{"id":1,"status":"active","activity_id":2,"instance_id":1,"user_id":1}]
- Activate a workitem:
curl -X POST http://localhost:8000/api/protected/workitems/1/activate \
-H "Authorization: Bearer <jwt>"
{"status":"activated","workitem_id":1}
- Complete a workitem:
curl -X POST http://localhost:8000/api/protected/workitems/1/complete \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{"condition":"APPROVED"}'
{"status":"completed","workitem_id":1}
- Start a process instance:
curl -X POST http://localhost:8000/api/protected/processes/start \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{"process_name":"leave","content_app_label":"leave","content_model":"leaverequest","object_id":1,"title":"Vacation request","priority":5}'
{"status":"started","workitem_id":12,"instance_id":9}
-
Error responses:
- 401/403: missing or invalid token
- 403: process or content type not allowed
- 403: object not allowed
- 400: invalid content type
- 404: content object not found
-
Schema summary:
SignInRequest
| Field | Type | Notes |
|---|---|---|
| username | string | Required |
| password | string | Required |
WebSignInResponse
| Field | Type | Notes |
|---|---|---|
| access | string | JWT access token |
MobileSignInResponse
| Field | Type | Notes |
|---|---|---|
| access | string | JWT access token |
| refresh | string | JWT refresh token |
ProcessOut
| Field | Type | Notes |
|---|---|---|
| id | integer | Process ID |
| title | string | Process title |
| enabled | boolean | Enabled flag |
ActivityOut
| Field | Type | Notes |
|---|---|---|
| id | integer | Activity ID |
| title | string | Activity title |
| kind | string | Activity kind |
| process_id | integer | Process ID |
WorkItemOut
| Field | Type | Notes |
|---|---|---|
| id | integer | Work item ID |
| status | string | Work item status |
| activity_id | integer | Activity ID |
| instance_id | integer | Process instance ID |
| user_id | integer or null | Assigned user ID |
StartProcessIn
| Field | Type | Notes |
|---|---|---|
| process_name | string | Process title |
| content_app_label | string | Django app label |
| content_model | string | Model name (lowercase) |
| object_id | integer | Object primary key |
| title | string or null | Optional instance title |
| priority | integer or null | Optional priority |
StartProcessResponse
| Field | Type | Notes |
|---|---|---|
| status | string | "started" |
| workitem_id | integer | First work item ID |
| instance_id | integer | Process instance ID |
- Optional API access controls (settings.py):
GOFLOW_API_ALLOWED_PROCESS_TITLES = ("leave", "Gestion des absences")
GOFLOW_API_ALLOWED_CONTENT_TYPES = ("leave.leaverequest",)
GOFLOW_API_REQUIRE_OBJECT_OWNERSHIP = True
GOFLOW_API_OBJECT_OWNER_FIELDS = ("requester",)
- Sampleproject note:
- Process titles: "Sample process", "test parallel workflow"
- Content type: "sampleapp.samplemodel"
Advanced example (summary):
- Parallel reviews: set
approve.split_mode = 'and'and addsecurity_reviewandfinance_reviewactivities, both leading tofinalizewithfinalize.join_mode = 'and'. - Timeout transition: add a transition with condition
workitem.time_out(3, unit='days')and rungoflow_cronto forward. - Exception path: set
instance.condition = 'EXCEPTION'and transition toexception_reviewfor manual recovery.
Leave demo data:
- PostgreSQL backup: leavedemo/pgdb/leavedemo20180517.backup
- SQLite fallback: sampleprojectdata.sqlite3
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_goflow2-1.1.tar.gz.
File metadata
- Download URL: django_goflow2-1.1.tar.gz
- Upload date:
- Size: 40.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
244e20c04d06d6df078dbe42dd70cc55fdb65a6c3f13df7c014f8919d67dbe83
|
|
| MD5 |
60b1b20ab3fe63e54d956ea923bb729e
|
|
| BLAKE2b-256 |
c64f0c0c71d423fcb66cd2044d1ad42551ad41a38535a2708a69c0ff538ee065
|
File details
Details for the file django_goflow2-1.1-py3-none-any.whl.
File metadata
- Download URL: django_goflow2-1.1-py3-none-any.whl
- Upload date:
- Size: 49.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4aa2e067aec0d9bc7176aae2d3045d1dad1b2e2006359c5e0bef90007e6bb197
|
|
| MD5 |
bb2a1504ed083e58fcafb83aebc25944
|
|
| BLAKE2b-256 |
a62e4faedf330ca9696b31691d37f084696e2e3b72e724ebc70afa05f617e583
|