Advanced Usage¶
Utility Methods ¶
These are available on your model instance when the mixin or extend the base model is used.
Method | Details |
---|---|
has_changed(field_name: str) -> bool |
Return a boolean indicating whether the field's value has changed since the model was initialized, or refreshed from db |
initial_value(field_name: str) -> bool |
Return the value of the field when the model was first initialized, or refreshed from db |
Example¶
You can use these methods for more advanced checks, for example:
from django_lifecycle import LifecycleModel, AFTER_UPDATE, hook
class UserAccount(LifecycleModel):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
marital_status = models.CharField(max_length=100)
@hook(AFTER_UPDATE)
def on_name_change_heck_on_marital_status(self):
if (
self.has_changed('last_name')
and not self.has_changed('marital_status')
):
send_mail(
to=self.email,
"Has your marital status changed recently?"
)
Custom conditions ¶
Custom conditions can be created as long as they respect condition signature
def changes_to_ned_flanders(instance, update_fields=None) -> bool:
return (
instance.has_changed("first_name")
and instance.has_changed("last_name")
and instance.first_name == "Ned"
and instance.last_name == "Flanders"
)
To allow your custom conditions to be chainable, create a class based condition inheriting ChainableCondition
.
from django_lifecycle import BEFORE_SAVE
from django_lifecycle.conditions import WhenFieldHasChanged
from django_lifecycle.conditions.base import ChainableCondition
class IsNedFlanders(ChainableCondition):
def __call__(self, instance, update_fields=None):
return (
instance.first_name == "Ned"
and instance.last_name == "Flanders"
)
@hook(
BEFORE_SAVE,
condition=(
WhenFieldHasChanged("first_name")
& WhenFieldHasChanged("last_name")
& IsNedFlanders()
)
)
def foo():
...
Suppressing Hooked Methods ¶
To prevent the hooked methods from being called, pass skip_hooks=True
when calling save: