Source code for core.orm.mixins.timestamp

from __future__ import annotations

from datetime import datetime
from sedate import utcnow
from sqlalchemy import func
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import mapped_column, Mapped


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from sqlalchemy.sql.elements import ColumnElement


[docs] class TimestampMixin: """ Mixin providing created/modified timestamps for all records. The columns are deferred loaded as this is primarily for logging and future forensics. """ @staticmethod
[docs] def timestamp() -> datetime: return utcnow()
[docs] created: Mapped[datetime] = mapped_column( default=timestamp, # FIXME: This should almost certainly have not been nullable, but # we need a migration for existing tables to fix this. nullable=True )
[docs] modified: Mapped[datetime | None] = mapped_column(onupdate=timestamp)
[docs] def force_update(self) -> None: """ Forces the model to update by changing the modified parameter. """ self.modified = self.timestamp()
@hybrid_property
[docs] def last_change(self) -> datetime: """ Returns the self.modified if not NULL, else self.created. """ return self.modified or self.created
@last_change.inplace.expression @classmethod
[docs] def _last_change_expression(cls) -> ColumnElement[datetime]: return func.coalesce(cls.modified, cls.created)