-
-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathmixins.py
More file actions
47 lines (38 loc) · 1.67 KB
/
mixins.py
File metadata and controls
47 lines (38 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from . import registry
from .i18n import _
class MachineMixin:
"""This mixing allows a model to automatically instantiate and assign an
``StateMachine``.
"""
state_field_name: str = "state"
"""The model's state field name that will hold the state value."""
state_machine_name: "str | None" = None
"""A fully qualified name of the class, where it can be imported."""
state_machine_attr: str = "statemachine"
"""Name of the model's attribute that will hold the machine instance."""
bind_events_as_methods: bool = False
"""If ``True`` the state machine events triggers will be bound to the model as methods."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.state_machine_name:
if self._is_django_historical_model():
return
raise ValueError(
_("{!r} is not a valid state machine name.").format(self.state_machine_name)
)
machine_cls = registry.get_machine_cls(self.state_machine_name)
sm = machine_cls(self, state_field=self.state_field_name)
setattr(
self,
self.state_machine_attr,
sm,
)
if self.bind_events_as_methods:
sm.bind_events_to(self)
@classmethod
def _is_django_historical_model(cls) -> bool:
"""Detect Django historical models created by ``apps.get_model()`` in migrations.
Django sets ``__module__ = '__fake__'`` on these dynamically-created classes,
which lack the user-defined class attributes like ``state_machine_name``.
"""
return getattr(cls, "__module__", None) == "__fake__"