fix: use clock_timestamp() instead of now() for Mixin to ensure unique values (#138)

This commit is contained in:
d3vyce
2026-03-14 17:30:11 +01:00
committed by GitHub
parent 0fb00d44da
commit 81407c3038
3 changed files with 11 additions and 13 deletions

View File

@@ -18,7 +18,7 @@ class Article(Base, UUIDMixin, TimestampMixin):
content: Mapped[str] content: Mapped[str]
``` ```
All timestamp columns are timezone-aware (`TIMESTAMPTZ`). All defaults are server-side, so they are also applied when inserting rows via raw SQL outside the ORM. All timestamp columns are timezone-aware (`TIMESTAMPTZ`). All defaults are server-side (`clock_timestamp()`), so they are also applied when inserting rows via raw SQL outside the ORM.
## Mixins ## Mixins
@@ -42,7 +42,7 @@ print(user.id) # UUID('...')
### [`CreatedAtMixin`](../reference/models.md#fastapi_toolsets.models.CreatedAtMixin) ### [`CreatedAtMixin`](../reference/models.md#fastapi_toolsets.models.CreatedAtMixin)
Adds a `created_at: datetime` column set to `NOW()` on insert. The column has no `onupdate` hook — it is intentionally immutable after the row is created. Adds a `created_at: datetime` column set to `clock_timestamp()` on insert. The column has no `onupdate` hook — it is intentionally immutable after the row is created.
```python ```python
from fastapi_toolsets.models import UUIDMixin, CreatedAtMixin from fastapi_toolsets.models import UUIDMixin, CreatedAtMixin
@@ -55,7 +55,7 @@ class Order(Base, UUIDMixin, CreatedAtMixin):
### [`UpdatedAtMixin`](../reference/models.md#fastapi_toolsets.models.UpdatedAtMixin) ### [`UpdatedAtMixin`](../reference/models.md#fastapi_toolsets.models.UpdatedAtMixin)
Adds an `updated_at: datetime` column set to `NOW()` on insert and automatically updated to `NOW()` on every ORM-level update (via SQLAlchemy's `onupdate` hook). Adds an `updated_at: datetime` column set to `clock_timestamp()` on insert and automatically updated to `clock_timestamp()` on every ORM-level update (via SQLAlchemy's `onupdate` hook).
```python ```python
from fastapi_toolsets.models import UUIDMixin, UpdatedAtMixin from fastapi_toolsets.models import UUIDMixin, UpdatedAtMixin

View File

@@ -1,9 +1,10 @@
import datetime
import uuid import uuid
from sqlalchemy import Boolean, DateTime, ForeignKey, String, Text, func from sqlalchemy import Boolean, ForeignKey, String, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from fastapi_toolsets.models import CreatedAtMixin
class Base(DeclarativeBase): class Base(DeclarativeBase):
pass pass
@@ -18,13 +19,10 @@ class Category(Base):
articles: Mapped[list["Article"]] = relationship(back_populates="category") articles: Mapped[list["Article"]] = relationship(back_populates="category")
class Article(Base): class Article(Base, CreatedAtMixin):
__tablename__ = "articles" __tablename__ = "articles"
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4) id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
created_at: Mapped[datetime.datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
title: Mapped[str] = mapped_column(String(256)) title: Mapped[str] = mapped_column(String(256))
body: Mapped[str] = mapped_column(Text) body: Mapped[str] = mapped_column(Text)
status: Mapped[str] = mapped_column(String(32)) status: Mapped[str] = mapped_column(String(32))

View File

@@ -3,7 +3,7 @@
import uuid import uuid
from datetime import datetime from datetime import datetime
from sqlalchemy import DateTime, Uuid, func, text from sqlalchemy import DateTime, Uuid, text
from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import Mapped, mapped_column
__all__ = [ __all__ = [
@@ -29,7 +29,7 @@ class CreatedAtMixin:
created_at: Mapped[datetime] = mapped_column( created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), DateTime(timezone=True),
server_default=func.now(), server_default=text("clock_timestamp()"),
) )
@@ -38,8 +38,8 @@ class UpdatedAtMixin:
updated_at: Mapped[datetime] = mapped_column( updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), DateTime(timezone=True),
server_default=func.now(), server_default=text("clock_timestamp()"),
onupdate=func.now(), onupdate=text("clock_timestamp()"),
) )