"""Templates (模板表) — the outlines a paper can be written against. A template is a named, ordered selection of library fields — the outline a paper is written against. It stores no typography of its own: font size and colour are read from the referenced :class:`~app.models.template_field_library.TemplateFieldLibrary`, so correcting a field's styling updates every template that uses it. """ from typing import TYPE_CHECKING from sqlalchemy import String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base from app.models.mixins import TimestampMixin if TYPE_CHECKING: # pragma: no cover - typing only from app.models.template_field import TemplateField class Template(TimestampMixin, Base): """A named outline: a template name, a summary, and its ordered fields.""" __tablename__ = "template" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(255), nullable=False) #: Free-text abstract (摘要) describing when to use this template. abstract: Mapped[str | None] = mapped_column(Text, nullable=True) #: The template's fields, always handed to callers in display order. #: #: ``delete-orphan`` is doing real work here: TiDB parses but does not #: enforce ``ON DELETE CASCADE``, so removing a template's rows in the join #: table is the ORM's job, not the database's. items: Mapped[list["TemplateField"]] = relationship( back_populates="template", cascade="all, delete-orphan", order_by="TemplateField.sort, TemplateField.id", lazy="selectin", ) def __repr__(self) -> str: # pragma: no cover - debugging aid return f"