Pre-save functionality¶
TL;DR¶
EspressoDB’s Base
class implements the .pre_save()
method which is run before .check_consistency()
and before inserting data into the database.
This functionality can be used to insert default values for columns that depend on runtime information.
Note
Similar to the .check_consistency()
method, .pre_save()
is not executed on bulk creation or update events.
Implementing a code version storage¶
The most prominent use case for employing a pre_save
check is to store code revision information.
For example
def get_code_revision() -> str:
"""Extracts version of code which generates data by ...
"""
return ...
BAD_REVISIONS = ["v0.7.6a", "v99.99.1b"]
class Data(Base):
value = models.FloatField(help_text="Important number")
tag = models.CharField(max_length=200, help_text="Code revision")
def pre_save(self):
"""Populates the `tag` column with the code revision.
This method is run before updating the database.
"""
self.tag = get_code_revision()
def check_consistency(self):
"""Checks if code used for generating data is not part of a bad revision.
This is run after `pre_save` but before inserting in the database.
"""
if self.tag in BAD_REVISIONS:
raise RuntimeError(
f"You should not use revision '{self.tag}' for exporting data."
)
If a user now runs
Data(value=6.123).save()
the Data
class will fill the tag
field with get_code_revision()
and only store entries if they are not part of BAD_REVISIONS
.
Similar to .check_consistency()
, .pre_save()
can be disabled for the whole class or for a single instance by the run_pre_save
attribute:
Data.run_pre_save = False # for all future instances
# or
instance = Data(value=1.23)
instance.run_pre_save = False # for only this instance