/
Ru5Kasper
/
Trackly
Обзор
Документация
Войти
/
Ru5Kasper
/
Trackly
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
backend/app/models.py
103 строки
4 KB
DORANDKOR
feat(backend): offline first
19 май 2026, 12:21
19 май 2026, 12:21
d70f9df
Код
Авторство
О чём код?
from __future__ import annotations from datetime import datetime, UTC from sqlalchemy import DateTime, ForeignKey, String, UniqueConstraint from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import mapped_column, Mapped, relationship from app.database import Base class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True, index=True) name: Mapped[str] = mapped_column() email: Mapped[str] = mapped_column(String(120), unique=True, nullable=False) password_hash: Mapped[str] = mapped_column(String(255), nullable=False) avatar_url: Mapped[str | None] = mapped_column( String(500), nullable=True, default=None ) habits: Mapped[list[Habit]] = relationship( back_populates="owner", cascade="all, delete-orphan" ) theme: Mapped[str] = mapped_column(String(30), default="light") disable_notifications: Mapped[bool] = mapped_column(default=False) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC), index=True ) @property def bool_theme(self) -> bool: match self.theme: case "dark": return True case "light": return False case _: return False @property def has_avatar(self) -> bool: return self.avatar_url is not None class Habit(Base): __tablename__ = "habits" __table_args__ = ( UniqueConstraint("user_id", "client_ref", name="uq_habits_user_id_client_ref"), ) id: Mapped[int] = mapped_column(primary_key=True, index=True) user_id: Mapped[int] = mapped_column( ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True ) title: Mapped[str] description: Mapped[str] color: Mapped[str] = mapped_column(String(7)) frequency: Mapped[int] target_count: Mapped[int] created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True ) deleted_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) client_ref: Mapped[str | None] = mapped_column(String(64), nullable=True) is_active: Mapped[bool] = mapped_column(default=False) schedule = mapped_column(JSONB, nullable=True) owner: Mapped[User] = relationship(back_populates="habits") logs: Mapped[list[HabitLog]] = relationship( back_populates="habit", cascade="all, delete-orphan" ) class HabitLog(Base): __tablename__ = "habit_logs" __table_args__ = ( UniqueConstraint( "habit_id", "client_ref", name="uq_habit_logs_habit_id_client_ref" ), ) id: Mapped[int] = mapped_column(primary_key=True, index=True) habit_id: Mapped[int] = mapped_column( ForeignKey("habits.id", ondelete="CASCADE"), nullable=False, index=True ) completed_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC) ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC), index=True ) deleted_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) client_ref: Mapped[str | None] = mapped_column(String(64), nullable=True) habit: Mapped[Habit] = relationship(back_populates="logs")