Model hooks¶
API Documentation
amsdal_models.classes.mixins.model_hooks_mixin.ModelHooksMixin
Model hooks allow you to insert custom logic into models based on certain events. Hooks as seperate python files in the JSON schema defintions, and as methods on the model class
Warning
Do not use .save()
or .delete()
methods in the hooks, as it may cause and error or unexpected behavior.
The pre_init
hook¶
This hook is called just before the model is initialized and the built-in validations are executed.
It accepts is_new_object
boolean argument that indicates if the model is being initialized as a new record or
existing one.
Also, it accepts kwargs: dict[str, Any]
argument that contains the keyword arguments that are passed to the model
constructor. Since the kwargs
is a dict, you can modify it in the hook and the changes will be applied
to the model constructor.
This hook is useful for setting default values for the model fields or for custome ETL or validation of keyword arguments.
Note
At this point the pydantic object is not fully initialized, so you need to check the kwargs
for the fields you want to modify.
Example
def pre_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
if is_new_object:
kwargs['name'] = 'Default Name'
if kwargs.get('custom_id_field'):
kwargs['_object_id'] = kwargs['custom_id_field']
The post_init
hook¶
This hook is called just after the model is initialized and the built-in validations are executed.
It accepts the same arguments as the pre_init
hook.
This hook also is useful for setting default values for the model fields or for extra validation of keyword arguments.
Note
Pydantic object is fully initialized and validated at this point, so you can access the fields directly, and set your custom fields here.
Example
def post_init(self, *, is_new_object: bool, kwargs: dict[str, Any]) -> None:
if is_new_object:
self.name = 'Default Name'
if self.name.islower():
msg = 'The name should not be written in lowercase'
raise ValueError(msg)
The pre_create
hook¶
This hook is called just before a new record of a model is saved to the database. It accepts self
as a single argument.
This hook is useful for setting default values for the first time before the creation of the object.
Note
At this stage object is not saved yet, so you cannot fetch the object from the database.
Example
def pre_create(self) -> None:
if not self.name:
self.name = 'Default Name'
The apre_create
hook¶
This hook is called just before a new record of a model is saved to the database. It accepts self
as a single argument.
This hook is useful for setting default values for the first time before the creation of the object.
Note
At this stage object is not saved yet, so you cannot fetch the object from the database.
Example
async def apre_create(self) -> None:
if not self.name:
self.name = 'Default Name'
The post_create
hook¶
This hook is called just after the new record of model is saved to the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is saved to the database. For example, sending a notification or starting a datapipeline to create additional records.
Example
def post_create(self) -> None:
PersonProfile(person=self).save()
The apost_create
hook¶
This hook is called just after the new record of model is saved to the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is saved to the database. For example, sending a notification or starting a datapipeline to create additional records.
Example
async def apost_create(self) -> None:
await PersonProfile(person=self).asave()
The pre_update
hook¶
This hook is called just before the existing record of model is updated in the database. It accepts self
as a single argument.
This hook is useful for validating the model before updating it in the database.
Note
Object version is not changed yet, so to check original version of the object to compare fields use .refetch_from_db()
method.
Example
def pre_update(self) -> None:
original_object = self.refetch_from_db()
if original_object.name != self.name:
msg = 'You cannot change the name of the object'
raise ValueError(msg)
The apre_update
hook¶
This hook is called just before the existing record of model is updated in the database. It accepts self
as a single argument.
This hook is useful for validating the model before updating it in the database.
Note
Object version is not changed yet, so to check original version of the object to compare fields use .refetch_from_db()
method.
Example
async def apre_update(self) -> None:
original_object = await self.arefetch_from_db()
if original_object.name != self.name:
msg = 'You cannot change the name of the object'
raise ValueError(msg)
The post_update
hook¶
This hook is called just after the existing record of model is updated in the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is updated in the database. For example, sending a notification or starting a datapipeline to create additional records.
Example
def post_update(self) -> None:
send_email(email=self.email, subject=f'Hi, {self.name}! Your profile has been updated')
The apost_update
hook¶
This hook is called just after the existing record of model is updated in the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is updated in the database. For example, sending a notification or starting a datapipeline to create additional records.
Example
async def apost_update(self) -> None:
send_email(email=self.email, subject=f'Hi, {self.name}! Your profile has been updated')
The pre_delete
hook¶
This hook is called just before the existing record of model is deleted from the database. It accepts self
as a single argument.
This hook is useful if you want to check if the record can be deleted or not.
Example
def pre_delete(self) -> None:
if self.account_balance < 0:
msg = 'You cannot delete the record with negative balance'
raise ValueError(msg)
The apre_delete
hook¶
This hook is called just before the existing record of model is deleted from the database. It accepts self
as a single argument.
This hook is useful if you want to check if the record can be deleted or not.
Example
astbc def apre_delete(self) -> None:
if self.account_balance < 0:
msg = 'You cannot delete the record with negative balance'
raise ValueError(msg)
The post_delete
hook¶
This hook is called just after the existing record of model is deleted from the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is deleted from the database. For example, you can send a notification to the user that the record is deleted.
Example
def post_delete(self) -> None:
send_email(email=self.email, subject=f'Hi, {self.name}! Your profile has been deleted')
The apost_delete
hook¶
This hook is called just after the existing record of model is deleted from the database. It accepts self
as a single argument.
This hook is useful for adding extra logic after the model is deleted from the database. For example, you can send a notification to the user that the record is deleted.
Example
async def apost_delete(self) -> None:
send_email(email=self.email, subject=f'Hi, {self.name}! Your profile has been deleted')
Info
You can read more about hooks in the AMSDAL CLI documentation.