Skip to content

Commit 910ce79

Browse files
committed
Fix get_available_FIELD_transition on django>=3.2. Close #256 #262
1 parent fda090b commit 910ce79

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed

django_fsm/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import django
1010
from django.db import models
11+
from django.db.models import Field
1112
from django.db.models.query_utils import DeferredAttribute
1213
from django.db.models.signals import class_prepared
1314
from django_fsm.signals import pre_transition, post_transition
@@ -403,7 +404,14 @@ def _collect_transitions(self, *args, **kwargs):
403404
def is_field_transition_method(attr):
404405
return (inspect.ismethod(attr) or inspect.isfunction(attr)) \
405406
and hasattr(attr, '_django_fsm') \
406-
and attr._django_fsm.field in [self, self.name]
407+
and (
408+
attr._django_fsm.field in [self, self.name]
409+
or (
410+
isinstance(attr._django_fsm.field, Field)
411+
and issubclass(self.model, attr._django_fsm.field.model)
412+
and attr._django_fsm.field.name == self.name
413+
and attr._django_fsm.field.creation_counter == self.creation_counter
414+
))
407415

408416
sender_transitions = {}
409417
transitions = inspect.getmembers(sender, predicate=is_field_transition_method)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from django.db import models
2+
from django.test import TestCase
3+
4+
from django_fsm import FSMField, transition, can_proceed
5+
6+
7+
class BaseAbstractModel(models.Model):
8+
state = FSMField(default='new')
9+
10+
class Meta:
11+
abstract = True
12+
13+
@transition(field=state, source='new', target='published')
14+
def publish(self):
15+
pass
16+
17+
18+
class InheritedFromAbstractModel(BaseAbstractModel):
19+
@transition(field='state', source='published', target='sticked')
20+
def stick(self):
21+
pass
22+
23+
24+
class TestinheritedModel(TestCase):
25+
def setUp(self):
26+
self.model = InheritedFromAbstractModel()
27+
28+
def test_known_transition_should_succeed(self):
29+
self.assertTrue(can_proceed(self.model.publish))
30+
self.model.publish()
31+
self.assertEqual(self.model.state, 'published')
32+
33+
self.assertTrue(can_proceed(self.model.stick))
34+
self.model.stick()
35+
self.assertEqual(self.model.state, 'sticked')
36+
37+
def test_field_available_transitions_works(self):
38+
self.model.publish()
39+
self.assertEqual(self.model.state, 'published')
40+
transitions = self.model.get_available_state_transitions()
41+
self.assertEqual(['sticked'], [data.target for data in transitions])
42+
43+
def test_field_all_transitions_works(self):
44+
transitions = self.model.get_all_state_transitions()
45+
self.assertEqual(set([('new', 'published'),
46+
('published', 'sticked')]),
47+
set((data.source, data.target) for data in transitions))

django_fsm/tests/test_protected_field.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class MultiProtectedAccessModel(models.Model):
1919
status1 = FSMField(default='new', protected=True)
2020
status2 = FSMField(default='new', protected=True)
2121

22+
class Meta:
23+
app_label = 'django_fsm'
24+
2225

2326
class TestDirectAccessModels(TestCase):
2427
def test_multi_protected_field_create(self):
File renamed without changes.

0 commit comments

Comments
 (0)