Skip to content

Add StartWorkflowMixin #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion joeflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .conf import settings
from .typing import HUMAN, MACHINE
from .utils import NoDashDiGraph
from .views import StartViewMixin

Check failure

Code scanning / CodeQL

Module-level cyclic import Error

'StartViewMixin' may not be defined if module
joeflow.views
is imported before module
joeflow.models
, as the
definition
of StartViewMixin occurs after the cyclic
import
of joeflow.models.

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -139,7 +140,7 @@
urls = []
for name, node in cls.get_nodes():
if isinstance(node, View):
if isinstance(node, BaseCreateView):
if isinstance(node, (BaseCreateView, StartViewMixin)):
route = f"{name}/"
else:
route = f"{name}/<int:pk>/"
Expand Down
4 changes: 2 additions & 2 deletions joeflow/tasks/human.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

from django.views import generic

from joeflow.views import TaskViewMixin
from joeflow.views import StartViewMixin, TaskViewMixin

__all__ = (
"StartView",
"UpdateView",
)


class StartView(TaskViewMixin, generic.CreateView):
class StartView(StartViewMixin, generic.CreateView):
"""
Start a new workflow by a human with a view.

Expand Down
19 changes: 19 additions & 0 deletions joeflow/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,25 @@ def create_task(self, workflow, prev_task):
)


class StartViewMixin(TaskViewMixin):
"""
View-mixin to create a start workflow.

Example:
class MyStartWorkflowView(StartViewMixin, View):
def post(self, request, *args, **kwargs):
try:
data = json.loads(request.body)
workflow_id = self.start_workflow(data)
except Exception as e:
return HttpResponseBadRequest("Failed to start workflow")

return JsonResponse({'message': 'Workflow started successfully.', 'id': workflow_id}, status=201)
"""

model = None


class WorkflowDetailView(WorkflowTemplateNameViewMixin, generic.DetailView):
pass

Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/simpleworkflow.dot
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ digraph {
"save the princess" [color=black fontcolor=black style="filled, rounded"]
"start method" [color=black fontcolor=black style=filled]
"start view" [color=black fontcolor=black style="filled, rounded"]
"custom start view" [color=black fontcolor=black style="filled, rounded"]
"save the princess" -> end [color=black]
"start method" -> "save the princess" [color=black]
"start view" -> "save the princess" [color=black]
"custom start view" -> "save the princess" [color=black]
}
2 changes: 2 additions & 0 deletions tests/fixtures/simpleworkflow_instance.dot
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ digraph {
"save the princess" [color=black fontcolor=black href="/simple/save_the_princess/2/" peripheries=1 style="filled, rounded, bold"]
"start method" [color=black fontcolor=black peripheries=1 style=filled]
"start view" [color="#888888" fontcolor="#888888" style="filled, rounded"]
"custom start view" [color="#888888" fontcolor="#888888" style="filled, rounded"]
"save the princess" -> end [color="#888888"]
"start method" -> "save the princess" [color=black]
"start view" -> "save the princess" [color="#888888"]
"custom start view" -> "save the princess" [color="#888888"]
}
1 change: 1 addition & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def test_urls(self):
assert namespace == "simpleworkflow"
names = {pattern.name for pattern in patterns}
assert names == {
"custom_start_view",
"save_the_princess",
"start_view",
"override",
Expand Down
8 changes: 8 additions & 0 deletions tests/testapp/workflows.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from datetime import timedelta

from django.core.mail import send_mail
from django.views import generic

from joeflow import tasks
from joeflow.views import StartViewMixin

from . import models
from .views import UpdateWithPrevUserView
Expand Down Expand Up @@ -40,8 +42,13 @@ class Meta:
proxy = True


class CustomStartViewTaskView(StartViewMixin, generic.View):
pass


class SimpleWorkflow(models.SimpleWorkflowState):
start_view = tasks.StartView(fields="__all__", path="custom/postfix/")
custom_start_view = CustomStartViewTaskView()
start_method = tasks.Start()
save_the_princess = tasks.UpdateView(fields="__all__")

Expand All @@ -50,6 +57,7 @@ def end(self):

edges = (
(start_view, save_the_princess),
(custom_start_view, save_the_princess),
(start_method, save_the_princess),
(save_the_princess, end),
)
Expand Down