State Visualization

Generate visual diagrams of your state machines.

Basic Chart Generation

The chart() function returns a DOT language representation:

from viewflow.fsm import chart
from myapp.flow import ReportFlow

dot_graph = chart(ReportFlow.state_field)
print(dot_graph)

Render the DOT output with Graphviz or similar tools.

Rendering in Django Views

Return the chart as plain text:

from django.http import HttpResponse
from viewflow.fsm import chart
from .flow import ReportFlow

def flow_chart_view(request):
    dot_graph = chart(ReportFlow.state_field)
    return HttpResponse(dot_graph, content_type='text/plain')

Or convert to PNG using pydot:

import pydot
from django.http import HttpResponse
from viewflow.fsm import chart
from .flow import ReportFlow

def flow_chart_image(request):
    dot_graph = chart(ReportFlow.state_field)

    graphs = pydot.graph_from_dot_data(dot_graph)
    graph = graphs[0]
    png_data = graph.create_png()

    return HttpResponse(png_data, content_type='image/png')

Chart Customization

from viewflow.fsm import chart
from .flow import ReportFlow

dot_graph = chart(
    ReportFlow,
    title="Report Approval Process",
    node_options={'shape': 'box', 'style': 'filled', 'fillcolor': '#f5f5f5'},
    edge_options={'fontsize': '11'},
    graph_options={'rankdir': 'LR'}  # Left to right layout
)

Admin and Viewset Integration

Charts are built into FlowAdminMixin and FlowViewsMixin. With these mixins, the chart appears on the change form or at the chart/ URL.

Example Output

A document review FSM in DOT format:

digraph {
    graph [rankdir=TB, size="8,8"];
    node [shape=box, style="filled", fillcolor="#f5f5f5", fontsize=10];
    edge [fontsize=9];

    NEW [label="NEW", fillcolor="#e1f5fe"];
    UNDER_REVIEW [label="UNDER REVIEW"];
    APPROVED [label="APPROVED"];
    REJECTED [label="REJECTED"];
    PUBLISHED [label="PUBLISHED", fillcolor="#e8f5e9"];

    NEW -> UNDER_REVIEW [label="submit"];
    UNDER_REVIEW -> APPROVED [label="approve"];
    UNDER_REVIEW -> REJECTED [label="reject"];
    APPROVED -> PUBLISHED [label="publish"];
    REJECTED -> NEW [label="revise"];
}