From b1553a07e79d5675fecd5535685d4722b8a81095 Mon Sep 17 00:00:00 2001 From: Mikhail Podgurskiy Date: Wed, 3 Sep 2014 11:29:43 +0700 Subject: [PATCH] Add on_error state draw --- README.md | 2 +- django_fsm/management/commands/graph_transitions.py | 12 ++++++++---- setup.py | 2 +- tests/testapp/models.py | 6 +++--- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1b1383ef..934c4121 100644 --- a/README.md +++ b/README.md @@ -324,7 +324,7 @@ Changelog django-fsm -### django-fsm GIT +### django-fsm 2.2.0 2014-09-03 * Support for [class substitution](http://schinckel.net/2013/06/13/django-proxy-model-state-machine/) to proxy classes depending on the state * Added ConcurrentTransitionMixin with optimistic locking support * Default db_index=True for FSMIntegerField removed diff --git a/django_fsm/management/commands/graph_transitions.py b/django_fsm/management/commands/graph_transitions.py index 3d1e9eb5..b4f8fea3 100644 --- a/django_fsm/management/commands/graph_transitions.py +++ b/django_fsm/management/commands/graph_transitions.py @@ -32,13 +32,17 @@ def generate_dot(fields_data): target_name = node_name(field, transition.target) sources.add((source_name, transition.source)) targets.add((target_name, transition.target)) - edges.add((source_name, target_name)) + edges.add((source_name, target_name, ())) + if transition.on_error: + on_error_name = node_name(field, transition.on_error) + targets.add((on_error_name, transition.on_error)) + edges.add((source_name, on_error_name, (('style', 'dotted'),))) for target in any_targets: target_name = node_name(field, target) targets.add((target_name, target)) for source_name, label in sources: - edges.add((source_name, target_name)) + edges.add((source_name, target_name, ())) # construct subgraph opts = field.model._meta @@ -48,8 +52,8 @@ def generate_dot(fields_data): for name, label in sources | targets: subgraph.node(name, label=label) - for source_name, target_name in edges: - subgraph.edge(source_name, target_name) + for source_name, target_name, attrs in edges: + subgraph.edge(source_name, target_name, **dict(attrs)) result.subgraph(subgraph) diff --git a/setup.py b/setup.py index a5e6636e..8f24056f 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name='django-fsm', - version='2.1.0', + version='2.2.0', description='Django friendly finite state machine support.', author='Mikhail Podgurskiy', author_email='kmmbvnr@gmail.com', diff --git a/tests/testapp/models.py b/tests/testapp/models.py index 3b959f6b..153dcb18 100644 --- a/tests/testapp/models.py +++ b/tests/testapp/models.py @@ -85,7 +85,7 @@ class BlogPost(models.Model): state = FSMField(default='new', protected=True) @transition(field=state, source='new', target='published', - permission='testapp.can_publish_post') + on_error='failed', permission='testapp.can_publish_post') def publish(self): pass @@ -93,12 +93,12 @@ def publish(self): def notify_all(self): pass - @transition(field=state, source='published', target='hidden') + @transition(field=state, source='published', target='hidden', on_error='failed',) def hide(self): pass @transition(field=state, source='new', target='removed', - permission=lambda u: u.has_perm('testapp.can_remove_post')) + on_error='failed', permission=lambda u: u.has_perm('testapp.can_remove_post')) def remove(self): raise Exception('No rights to delete %s' % self)