o2o-castad-backend/app/lyrics/models-refer.py

159 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from app.core.database import Base
from sqlalchemy import (
Boolean,
DateTime,
Enum,
ForeignKey,
Index,
Integer,
PrimaryKeyConstraint,
String,
func,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from starlette.authentication import BaseUser
class User(Base, BaseUser):
__tablename__ = "users"
id: Mapped[int] = mapped_column(
Integer, primary_key=True, nullable=False, autoincrement=True
)
username: Mapped[str] = mapped_column(
String(255), unique=True, nullable=False, index=True
)
email: Mapped[str] = mapped_column(
String(255), unique=True, nullable=False, index=True
)
hashed_password: Mapped[str] = mapped_column(String(60), nullable=False)
# age_level 컬럼을 Enum으로 정의
age_level_choices = ["10", "20", "30", "40", "50", "60", "70", "80"]
age_level: Mapped[str] = mapped_column(
Enum(*age_level_choices, name="age_level_enum"),
nullable=False,
default="10",
)
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[DateTime] = mapped_column(DateTime, server_default=func.now())
# One-to-many relationship with Post (DynamicMapped + lazy="dynamic")
posts_user: Mapped[list["Post"]] = relationship("Post", back_populates="user_posts")
# # Many-to-many relationship with Group
# user_groups: DynamicMapped["UserGroupAssociation"] = relationship(
# "UserGroupAssociation", back_populates="user", lazy="dynamic"
# )
# n:m 관계 (Group) 최적의 lazy 옵션: selectin
group_user: Mapped[list["Group"]] = relationship(
"Group",
secondary="user_group_association",
back_populates="user_group",
lazy="selectin",
)
def __repr__(self) -> str:
return f"id={self.id}, username={self.username}"
@property
def is_authenticated(self) -> bool:
return self.is_active
@property
def display_name(self) -> str:
return self.username
@property
def identity(self) -> str:
return self.username
# 1:N Relationship - Posts
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
)
title: Mapped[str] = mapped_column(String(255), nullable=False)
content: Mapped[str] = mapped_column(String(10000), nullable=False)
is_published: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[DateTime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[DateTime] = mapped_column(
DateTime, server_default=func.now(), onupdate=func.now()
)
# tags: Mapped[dict] = mapped_column(MutableDict.as_mutable(JSONB), default=[]) // sqlite 지원 안함
view_count: Mapped[int] = mapped_column(Integer, default=0)
# Many-to-one relationship with User (using dynamic loading)
user_posts: Mapped["User"] = relationship("User", back_populates="posts_user")
def __repr__(self) -> str:
return f"Post(id={self.id}, user_id={self.user_id}, title={self.title})"
__table_args__ = (
Index("idx_posts_user_id", "user_id"),
Index("idx_posts_created_at", "created_at"),
Index(
"idx_posts_user_id_created_at", "user_id", "created_at"
), # Composite index
)
# N:M Relationship - Users and Groups
# Association table for many-to-many relationship
# N:M Association Table (중간 테이블)
class UserGroupAssociation(Base):
__tablename__ = "user_group_association"
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id", ondelete="CASCADE"), primary_key=True
)
group_id: Mapped[int] = mapped_column(
Integer, ForeignKey("groups.id", ondelete="CASCADE"), primary_key=True
)
# # 관계 정의
# user: Mapped["User"] = relationship("User", back_populates="user_groups")
# group: Mapped["Group"] = relationship("Group", back_populates="group_users")
# # 복합 기본 키 설정
# 기본 키 설정을 위한 __table_args__ 추가
__table_args__ = (PrimaryKeyConstraint("user_id", "group_id"),)
def __repr__(self) -> str:
return f"UserGroupAssociation(user_id={self.user_id}, group_id={self.group_id})"
# Group 테이블
class Group(Base):
__tablename__ = "groups"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True)
description: Mapped[str] = mapped_column(String(1000))
is_public: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[DateTime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[DateTime] = mapped_column(
DateTime, server_default=func.now(), onupdate=func.now()
)
user_group: Mapped[list["User"]] = relationship(
"User",
secondary="user_group_association",
back_populates="group_user",
lazy="selectin",
)
# Group을 만든 사용자와 관계 (일반적인 1:N 관계)
def __repr__(self) -> str:
return f"Group(id={self.id}, name={self.name})"
__table_args__ = (
Index("idx_groups_name", "name"),
Index("idx_groups_is_public", "is_public"),
Index("idx_groups_created_at", "created_at"),
Index("idx_groups_composite", "is_public", "created_at"),
)