Changeset View
Changeset View
Standalone View
Standalone View
looper/model_mixins.py
| import copy | import copy | ||||
| from typing import Any, Mapping, Set, Tuple, Union | from typing import Any, Mapping, Set, Tuple, Union | ||||
| from django.db import models | from django.db import models | ||||
| from django.db.models.expressions import Combinable | |||||
| OldStateType = Mapping[str, Any] | OldStateType = Mapping[str, Any] | ||||
| """Type declaration for the old state of a model instance. | """Type declaration for the old state of a model instance. | ||||
| See RecordModificationMixin.pre_save_record(). | See RecordModificationMixin.pre_save_record(). | ||||
| """ | """ | ||||
| Show All 16 Lines | class RecordModifcationMixin(models.Model): | ||||
| Only acts on fields listed in self.record_modification_fields. | Only acts on fields listed in self.record_modification_fields. | ||||
| """ | """ | ||||
| class Meta: | class Meta: | ||||
| abstract = True | abstract = True | ||||
| record_modification_fields: Set[str] | record_modification_fields: Set[str] | ||||
| def _check_modification(self, old_instance) -> bool: | def _check_modification(self, old_instance: object) -> bool: | ||||
| """Returns True iff the membership was modified. | """Returns True iff the membership was modified. | ||||
| Only checks fields listed in self.record_modification_fields. | Only checks fields listed in self.record_modification_fields. | ||||
| """ | """ | ||||
| for field in self.record_modification_fields: | for field in self.record_modification_fields: | ||||
| old_val = getattr(old_instance, field, ...) | old_val = getattr(old_instance, field, ...) | ||||
| new_val = getattr(self, field, ...) | new_val = getattr(self, field, ...) | ||||
| Show All 36 Lines | class Meta: | ||||
| abstract = True | abstract = True | ||||
| # Map 'current status': {set of allowed new statuses}; define in subclass: | # Map 'current status': {set of allowed new statuses}; define in subclass: | ||||
| VALID_STATUS_TRANSITIONS: Mapping[str, Set[str]] | VALID_STATUS_TRANSITIONS: Mapping[str, Set[str]] | ||||
| # Add this field in a subclass, so that it uses the subclass' STATUSES | # Add this field in a subclass, so that it uses the subclass' STATUSES | ||||
| # and DEFAULT_STATUS values: | # and DEFAULT_STATUS values: | ||||
| # status = models.CharField(choices=STATUSES, default=DEFAULT_STATUS, max_length=20) | # status = models.CharField(choices=STATUSES, default=DEFAULT_STATUS, max_length=20) | ||||
| status: str | status: 'models.CharField[Union[str, int, Combinable], str]' | ||||
| def may_transition_to(self, new_status: str) -> bool: | def may_transition_to(self, new_status: str) -> bool: | ||||
| """Validate the potential transition from the current status to 'new_status'.""" | """Validate the potential transition from the current status to 'new_status'.""" | ||||
| try: | try: | ||||
| valid_transitions = self.VALID_STATUS_TRANSITIONS[self.status] | valid_transitions = self.VALID_STATUS_TRANSITIONS[self.status] | ||||
| except KeyError: | except KeyError: | ||||
| return False | return False | ||||
| return new_status in valid_transitions | return new_status in valid_transitions | ||||