Reusable library to build business applications fast
Project description
Viewflow
The low-code for developers with yesterday's deadline
Viewflow is a low-code library for building business applications with Django. It gives you ready-made components for user management, workflows, and reporting. You write less code but keep full control. You can customize everything and connect it to your existing systems.
Build full-featured business applications in a few lines of code. Viewflow ships as one package with everything included. Each part works on its own, but they all work well together.
GPT assisted with Viewflow documentation: Viewflow Pair Programming Buddy
Viewflow comes in two versions:
- Viewflow Core: Open-source library with base classes. Build your own solution on top.
- Viewflow PRO: Full package with ready-to-use features and third-party integrations. Commercial license allows private forks and modifications.
Features
- Modern, responsive interface with SPA-style navigation
- Reusable workflow library for BPMN processes
- Built-in CRUD for complex forms and data
- Reporting dashboard included
- Small, easy-to-learn API
Installation
Viewflow works with Python 3.10+ and Django 4.2+
Viewflow:
pip install django-viewflow
Viewflow PRO:
pip install django-viewflow-pro --extra-index-url https://pypi.viewflow.io/<licence_id>/simple/
Add to INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
....
'viewflow',
'viewflow.workflow', # if you need workflows
]
Quick start
Here is a pizza ordering workflow example.
1. Create a model for process data
Viewflow provides a Process base model. Use jsonstore fields to store data without extra database joins:
from viewflow import jsonstore
from viewflow.workflow.models import Process
class PizzaOrder(Process):
customer_name = jsonstore.CharField(max_length=250)
address = jsonstore.TextField()
toppings = jsonstore.TextField()
tips_received = jsonstore.IntegerField(default=0)
baking_time = jsonstore.IntegerField(default=10)
class Meta:
proxy = True
2. Create flows.py with your workflow
Define a flow class with steps. Use CreateProcessView and UpdateProcessView for the forms:
from viewflow import this
from viewflow.workflow import flow
from viewflow.workflow.flow.views import CreateProcessView, UpdateProcessView
from .models import PizzaOrder
class PizzaFlow(flow.Flow):
process_class = PizzaOrder
start = flow.Start(
CreateProcessView.as_view(
fields=["customer_name", "address", "toppings"]
)
).Next(this.bake)
bake = flow.View(
UpdateProcessView.as_view(fields=["baking_time"])
).Next(this.deliver)
deliver = flow.View(
UpdateProcessView.as_view(fields=["tips_received"])
).Next(this.end)
end = flow.End()
3. Add URLs
Register the workflow with the frontend:
from django.urls import path
from viewflow.contrib.auth import AuthViewset
from viewflow.urls import Application, Site
from viewflow.workflow.flow import FlowAppViewset
from my_pizza.flows import PizzaFlow
site = Site(
title="Pizza Flow Demo",
viewsets=[
FlowAppViewset(PizzaFlow, icon="local_pizza"),
]
)
urlpatterns = [
path("accounts/", AuthViewset().urls),
path("", site.urls),
]
4. Run migrations and start the server
Run migrations, start Django, and open the browser. You can now create and track pizza orders through the workflow.
Next steps: https://docs.viewflow.io/workflow/writing.html
Documentation
Latest version: http://docs.viewflow.io/
Version 1.xx: http://v1-docs.viewflow.io
Demo
Cookbook
Code samples and examples: https://github.com/viewflow/cookbook
Stay updated
Subscribe to our newsletter for release notes, Django low-code tips, and notes on shipping business apps fast.
License
Viewflow is an Open Source project licensed under the terms of the AGPL license - The GNU Affero General Public License v3.0 with the Additional Permissions described in LICENSE_EXCEPTION
The AGPL license with Additional Permissions is a free software license that allows commercial use and distribution of the software. It is similar to the GNU GCC Runtime Library license, and it includes additional permissions that make it more friendly for commercial development.
You can read more about AGPL and its compatibility with commercial use at the AGPL FAQ
If you use Linux already, this package license likely won't bring anything new to your stack.
Viewflow PRO has a commercial-friendly license allowing private forks and modifications of Viewflow. You can find the commercial license terms in COMM-LICENSE.
Changelog
For older releases, see CHANGELOG.rst.
2.4.0 2026-07-30
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.
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_viewflow-2.4.0.tar.gz.
File metadata
- Download URL: django_viewflow-2.4.0.tar.gz
- Upload date:
- Size: 24.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbce804262f2d5d41d87383042670d1adf003d3952823742a2e35cfff7212768
|
|
| MD5 |
1ea8809e08c295d5895864d5d975c21f
|
|
| BLAKE2b-256 |
ebafd55b421c4065bbb506ae57cc46e27b8eb43d2a1133c65ec1a8d06282d21f
|
File details
Details for the file django_viewflow-2.4.0-py3-none-any.whl.
File metadata
- Download URL: django_viewflow-2.4.0-py3-none-any.whl
- Upload date:
- Size: 24.8 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3d2b5b2ca46b4e54f2162b9faaadc01cb47629f87e5c6b03f93ade4af4f27bb
|
|
| MD5 |
8f5059fea3eeffdd3ac403bea91e9053
|
|
| BLAKE2b-256 |
3dff8aa0cf50a3bef70ce158bc2e4dd865b98d9ee250eae10d9dbfbf62fed66c
|