75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
"""Base SQLAlchemy declarative base for all database models.
|
|
|
|
This module provides the base class that all ORM models inherit from,
|
|
along with common functionality and mixins.
|
|
"""
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
|
|
from sqlalchemy import DateTime, func
|
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
"""Base class for all SQLAlchemy ORM models.
|
|
|
|
Provides common functionality and type annotations for all models.
|
|
All models should inherit from this class.
|
|
"""
|
|
pass
|
|
|
|
|
|
class TimestampMixin:
|
|
"""Mixin to add created_at and updated_at timestamp columns.
|
|
|
|
Automatically tracks when records are created and updated.
|
|
Use this mixin for models that need audit timestamps.
|
|
|
|
Attributes:
|
|
created_at: Timestamp when record was created
|
|
updated_at: Timestamp when record was last updated
|
|
"""
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
nullable=False,
|
|
doc="Timestamp when record was created"
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False,
|
|
doc="Timestamp when record was last updated"
|
|
)
|
|
|
|
|
|
class SoftDeleteMixin:
|
|
"""Mixin to add soft delete functionality.
|
|
|
|
Instead of deleting records, marks them as deleted with a timestamp.
|
|
Useful for maintaining audit trails and allowing recovery.
|
|
|
|
Attributes:
|
|
deleted_at: Timestamp when record was soft deleted, None if active
|
|
"""
|
|
deleted_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=True,
|
|
default=None,
|
|
doc="Timestamp when record was soft deleted"
|
|
)
|
|
|
|
@property
|
|
def is_deleted(self) -> bool:
|
|
"""Check if record is soft deleted."""
|
|
return self.deleted_at is not None
|
|
|
|
def soft_delete(self) -> None:
|
|
"""Mark record as deleted without removing from database."""
|
|
self.deleted_at = datetime.now(timezone.utc)
|
|
|
|
def restore(self) -> None:
|
|
"""Restore a soft deleted record."""
|
|
self.deleted_at = None
|