| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| django_viewflow-2.4.0-py3-none-any.whl | 2026-07-30 | 24.8 MB | |
| django_viewflow-2.4.0.tar.gz | 2026-07-30 | 24.7 MB | |
| 2.4.0 -- BPMN 2.0 completeness, JSON Store documents, django-fsm drop-in source code.tar.gz | 2026-07-30 | 22.3 MB | |
| 2.4.0 -- BPMN 2.0 completeness, JSON Store documents, django-fsm drop-in source code.zip | 2026-07-30 | 22.6 MB | |
| README.md | 2026-07-30 | 7.3 kB | |
| Totals: 5 Items | 94.4 MB | 2 | |
The largest feature release of the 2.x line: complete BPMN 2.0 node coverage, document-oriented JSON Store fields, and a drop-in replacement for django-fsm.
Workflow and BPMN
- New database-backed
flow.Timerandflow.StartTimer(interval=...)nodes. The due moment is stored on the task row (newTask.scheduledfield, migration included), so a timer survives a broker restart, unlikecelery.Timer. Due timers fire from theworkflow_timersmanagement command or theworkflow_fire_timerscelery beat task - Boundary events, declared on the host task before
.Next():.OnTimeout(delay, then)for deadlines and escalation,.OnError(then, code=...)to catch a background task failure. Interrupting by default;interrupting=Falsestarts a parallel path flow.TerminateEnd()cancels all other active tasks and finishes the process;flow.ErrorEnd(code)fails it. Inside a subprocess,ErrorEndmarks the parent taskERROR, so the parent's.OnError(..., code=...)boundary catches it- Compensation:
.CompensateWith(this.handler)registers an undo handler on any task, andflow.CompensateThrow()runs the handlers of completed tasks in reverse completion order, each at most once - New intermediate events:
MessageCatch/MessageThrow,SignalCatch/SignalThrow(one throw releases every armed catch, across processes and flow classes),EscalationThrowwith a non-interrupting.OnEscalationboundary, andConditionalCatch, which waits until a condition over process data holds - New task types:
flow.SendHandle,flow.BusinessRule, andflow.ManualTaskfor work done outside any system, marked done with a no-field confirmation.NSubprocess(..., sequential=True)runs one child process at a time - BPMN 2.0 export overhaul: exported files validate against the official OMG
schema and open in bpmn.io and Camunda Modeler.
Switch,SubprocessandNSubprocessare no longer dropped from the export,Handlemaps to a receive task, celeryJobto a service task, and the new nodes above to their real BPMN counterparts. Download a flow as.bpmnfrom the chart view, the REST API (?format=bpmn), the diagram dialog, or theflowexportcommand - Chart layout: empty grid rows and columns are collapsed, cell collisions
resolved, parallel edge channels staggered and routed around node shapes, and
Ifbranches labeled yes/no - The flow diagram dialog is now pan- and zoom-able: scroll to zoom toward the cursor, drag to pan, pinch on touch, double-click to reset
- Every built-in control node is cancellable,
Flow.cancelraises the intendedFlowRuntimeErrorinstead ofAttributeErrorfor a node with nocanceltransition, and the process cancel view refuses cleanly instead of returning a 500 when a task can't be cancelled flow.Viewgained areassign_view_classhook that finishes the built-in reassign transition and shows a "Reassign" action on the task (off by default)- New cookbook samples, all in application code with no core changes:
substitute(reassignment),snooze(hide a task from the inbox until a chosen time, [#219]), anddynamic_subprocess(attach anotherNSubprocesschild while the parent task still runs, [#258])
JSON Store
- Relation fields stored inside the JSON document, with no column, migration or
join table:
jsonstore.ForeignKey(pk under<name>_id, lazy load,ModelChoiceFieldin forms),jsonstore.OneToOneField, andjsonstore.ManyToManyField(a manager withall/add/remove/set/clear/count). Non-integer primary keys, e.g.UUIDField, are supported (#366) jsonstore.EmbeddedModelwithEmbeddedFieldandEmbeddedListField: schema-only virtual models (typed fields, no table) stored as a nested JSON document, or a list of them. Embedded models nest, and reading returns an instance bound to the stored sub-document, so in-place edits are savedviewflow.formsedits embedded documents as nested forms:EmbeddedModelFormbuilds a form from an embedded schema, andEmbeddedFormField/EmbeddedFormSetFieldbind it to the model field, so a document edits as a nested form and a list of them as inlines, all in one JSON column. Newcookbook/embed101demo- New field types:
BigIntegerField,SmallIntegerField, the threePositive*IntegerFields,SlugField,FilePathField,UUIDField,DurationField(ISO-8601, read back as atimedelta) andBinaryField(base64, read back asbytes) - A
json_keyargument controls where a value lives in the document: a custom key, or a list/tuple for a nested path (json_key=("address", "city")), honored by reading, writing, filtering and ordering for every field type
FSM
viewflow.fsm.FSMField: a same-column drop-in for django-fsm'sFSMField. Swap the import and@transition(field=..., source=..., target=...)keeps working, on top of theconditions/permission/on_successmachineryviewflow.fsmalready has. Two guarantees django-fsm didn't have are opt-in and off by default:protected=Trueblocks direct assignment after the first value is set, andenforce_initial=TrueraisesNonInitialStateOnCreatewhen a new row would be inserted at a non-default value- Dynamic transition targets, ported from django-fsm:
target=State.RETURN_VALUE(*states)takes the target from the method's return value, andtarget=State.GET_STATE(func, states=[...])computes it from the call's arguments before the method runs. Declared states are charted and enforced withInvalidTargetState TransitionNotAllowedsplit intoNoTransition(nothing registered from the current state) andTransitionConditionsUnmet(aconditions=callback returned false, carrying the failed condition and its message). Existingexcept TransitionNotAllowedhandlers keep working- The
FlowViewsMixinlist page shows the state diagram next to the object table in a click-to-zoom dialog, exportable as PNG. The admin change-list diagram no longer blows out the filter sidebar
Viewsets and forms
- A virtual list column (a viewset or model method or property) can be made
sortable with
orderby_column— a field lookup like"data__price", or a query expression likeCast("data__price", IntegerField())for a numeric sort (#361) - Bulk actions now scope their queryset through the viewset's
get_queryset(request), so "Select All" no longer touches rows outside the viewset's scope, and no longer crash for a viewset with no configured filter (#422) InlineFormSetFieldand the other composite fields honor a field-levelinitial=[...]as a fallback, so pre-populated formset rows render their valuesprocess_dashboard.htmlexposes aflow_start_card_actionsblock, so projects can add start-card controls by extending the template instead of copying it
Plus fixes for a 500 on the admin process changelist (#523) and on the task detail page of an unregistered subprocess. See CHANGELOG.rst for the full list.
Install
pip install django-viewflow==2.4.0
Full changelog: https://github.com/viewflow/viewflow/blob/main/CHANGELOG.rst Docs: https://docs.viewflow.io/