__tablename__='xxx'的使用

博客主要提及在flask框架里创建表时修改表名的操作,且指出相关代码应放在models.py文件下。

在flask框架中创建表的时候修改表名
这段话放在models.py下
在这里插入图片描述

# models.py from datetime import datetime, timezone from sqlalchemy import ( Column, Integer, String, Text, Boolean, DateTime, ForeignKey, Enum, Index, UniqueConstraint, ) from sqlalchemy.orm import declarative_base, relationship from typing import Optional Base = declarative_base() def utcnow(): return datetime.now(timezone.utc) class Department(Base): __tablename__ = "departments" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), unique=True, nullable=False, index=True) description = Column(Text, nullable=True) created_at = Column(DateTime, default=utcnow) # 关系 users = relationship("User", back_populates="department") rooms = relationship("Room", back_populates="department") class Character(Base): __tablename__ = "characters" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), unique=True, nullable=False, index=True) trait = Column(Text, nullable=False) avatar_url = Column(String(255), default="/static/avatars/ai_default.png", nullable=False) created_at = Column(DateTime, default=utcnow) # 关系 shares = relationship("Share", back_populates="ai_character") conversations = relationship("UserConversation", back_populates="character") rooms = relationship("Room", back_populates="ai_character") class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) account = Column(String(50), unique=True, nullable=False, index=True) password = Column(String(255), nullable=False) role = Column(Enum("user", "dept_admin", "admin"), nullable=False, default="user") department_id = Column(Integer, ForeignKey("departments.id"), nullable=True) created_at = Column(DateTime, default=utcnow) # 关系 department = relationship("Department", back_populates="users") profile = relationship("UserProfile", uselist=False, back_populates="user", cascade="all, delete-orphan") rooms_created = relationship("Room", back_populates="creator") room_memberships = relationship("RoomMember", back_populates="user") shares = relationship("Share", back_populates="author") comments = relationship("Comment", back_populates="commenter") search_records = relationship("SearchRecord", back_populates="user") likes = relationship("ShareLike", back_populates="user") conversations = relationship("UserConversation", back_populates="user") class UserProfile(Base): __tablename__ = "user_profiles" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False, unique=True) personality = Column(Text, nullable=True) role_setting = Column(Text, nullable=True) updated_at = Column(DateTime, default=utcnow, onupdate=utcnow) # 关系 user = relationship("User", back_populates="profile") class Share(Base): __tablename__ = "shares" id = Column(Integer, primary_key=True, index=True) title = Column(String(200), nullable=False) content = Column(Text, nullable=False) author_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) is_public = Column(Boolean, default=True, index=True) type = Column(Enum("public", "private", "dept"), nullable=False, default="public") ai_character_id = Column(Integer, ForeignKey("characters.id"), nullable=True, index=True) view_count = Column(Integer, default=0) like_count = Column(Integer, default=0) comment_count = Column(Integer, default=0) created_at = Column(DateTime, default=utcnow) # 关系 author = relationship("User", back_populates="shares") ai_character = relationship("Character", back_populates="shares") likes = relationship("ShareLike", back_populates="share", cascade="all, delete-orphan") comments = relationship("Comment", back_populates="share", cascade="all, delete-orphan") class SearchRecord(Base): __tablename__ = "search_records" id = Column(Integer, primary_key=True, index=True) keyword = Column(String(100), nullable=False, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=True, index=True) search_time = Column(DateTime, default=utcnow) # 关系 user = relationship("User", back_populates="search_records") # 全文索引(需手动创建) __table_args__ = ( Index("idx_search_time", "search_time"), Index("idx_user_id_time", "user_id", "search_time"), ) class Room(Base): __tablename__ = "rooms" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), nullable=False) type = Column(Enum("public", "dept", "ai"), nullable=False) # public, dept, ai dept_id = Column(Integer, ForeignKey("departments.id"), nullable=True) ai_character_id = Column(Integer, ForeignKey("characters.id"), nullable=True) description = Column(Text, nullable=True) creator_id = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime, default=utcnow) # 关系 creator = relationship("User", back_populates="rooms_created") department = relationship("Department", back_populates="rooms") ai_character = relationship("Character", back_populates="rooms") members = relationship("RoomMember", back_populates="room", cascade="all, delete-orphan") messages = relationship("RoomMessage", back_populates="room", cascade="all, delete-orphan") class RoomMember(Base): __tablename__ = "room_members" id = Column(Integer, primary_key=True) room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) joined_at = Column(DateTime, default=utcnow) # 唯一性约束 __table_args__ = (UniqueConstraint("room_id", "user_id", name="uk_room_user"),) # 关系 room = relationship("Room", back_populates="members") user = relationship("User", back_populates="room_memberships") class RoomMessage(Base): __tablename__ = "room_messages" id = Column(Integer, primary_key=True) room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False, index=True) sender_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) content = Column(Text, nullable=False) sent_at = Column(DateTime, default=utcnow) # 关系 room = relationship("Room", back_populates="messages") sender = relationship("User") class Comment(Base): __tablename__ = "comments" id = Column(Integer, primary_key=True) share_id = Column(Integer, ForeignKey("shares.id"), nullable=False, index=True) commenter_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) parent_id = Column(Integer, ForeignKey("comments.id"), nullable=True, index=True) content = Column(Text, nullable=False) created_at = Column(DateTime, default=utcnow) # 子评论列表("一" 的那一边) replies = relationship( "Comment", back_populates="parent", # 不用 backref,显式控制 lazy="selectin", cascade="all, delete-orphan", # ✅ 正确位置:父级控制子级生命周期 foreign_keys=[parent_id] # 明确指定外键 ) # 父评论引用("多" 的那一边) parent = relationship( "Comment", back_populates="replies", remote_side=[id], # 标记谁是“根” lazy="select" ) # 其他关系保持不变... share = relationship("Share", back_populates="comments") commenter = relationship("User", back_populates="comments") class ShareLike(Base): __tablename__ = "share_likes" id = Column(Integer, primary_key=True) share_id = Column(Integer, ForeignKey("shares.id"), nullable=False, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) liked_at = Column(DateTime, default=utcnow) # 唯一性约束 __table_args__ = (UniqueConstraint("share_id", "user_id", name="uk_share_user"),) # 关系 share = relationship("Share", back_populates="likes") user = relationship("User", back_populates="likes") class UserConversation(Base): __tablename__ = "user_conversations" id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) character_id = Column(Integer, ForeignKey("characters.id"), nullable=False, index=True) user_message = Column(Text, nullable=False) ai_message = Column(Text, nullable=False) timestamp = Column(DateTime, default=utcnow) # 关系 user = relationship("User", back_populates="conversations") character = relationship("Character", back_populates="conversations") # 复合索引 __table_args__ = ( Index("idx_user_char_time", "user_id", "character_id", "timestamp"), ) # schemas.py from pydantic import BaseModel, Field, field_validator from typing import Optional, List, Dict, Any from datetime import datetime, date from enum import Enum as PyEnum # ====================== # 公共枚举类 # ====================== class RoleType(PyEnum): user = "user" dept_admin = "dept_admin" admin = "admin" class RoomType(PyEnum): public = "public" dept = "dept" ai = "ai" class ShareType(PyEnum): public = "public" private = "private" dept = "dept" # ====================== # 用户相关 Schema # ====================== class UserCreate(BaseModel): account: str = Field(..., min_length=1, max_length=50, description="用户名(学号或邮箱前缀)") password: str = Field(..., min_length=6, max_length=128, description="登录密码") department_id: Optional[int] = Field(None, ge=1, description="所属院系ID") @field_validator("password") def validate_password(cls, v): if len(v) < 6: raise ValueError("密码至少6位") return v class UserUpdate(BaseModel): password: Optional[str] = Field(None, min_length=6, max_length=128) department_id: Optional[int] = Field(None, ge=1) class UserProfile(BaseModel): personality: Optional[str] = None role_setting: Optional[str] = None updated_at: datetime class UserOut(BaseModel): id: int account: str role: RoleType department_id: Optional[int] created_at: datetime class Config: arbitrary_types_allowed = True class UserDetailOut(UserOut): department_name: Optional[str] = None profile: Optional[UserProfile] = None # ====================== # 院系相关 Schema # ====================== class DepartmentCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) description: Optional[str] = Field("", max_length=500) class DepartmentOut(BaseModel): id: int name: str description: Optional[str] created_at: datetime class Config: arbitrary_types_allowed = True # ====================== # AI角色相关 Schema # ====================== class CharacterBase(BaseModel): id: int name: str trait: str avatar_url: str created_at: datetime class Config: arbitrary_types_allowed = True class CharacterCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) trait: str = Field(..., min_length=1) avatar_url: Optional[str] = "/static/avatars/ai_default.png" class CharacterUpdate(BaseModel): name: Optional[str] = Field(None, min_length=1, max_length=100) trait: Optional[str] = Field(None, min_length=1) avatar_url: Optional[str] = None # ====================== # 聊天室相关 Schema # ====================== class RoomCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) type: RoomType dept_id: Optional[int] = None ai_character_id: Optional[int] = None description: Optional[str] = Field(None, max_length=500) class RoomOut(BaseModel): id: int name: str type: RoomType dept_id: Optional[int] ai_character_id: Optional[int] description: Optional[str] creator_id: int created_at: datetime class Config: arbitrary_types_allowed = True class MessageCreate(BaseModel): content: str = Field(..., min_length=1, max_length=2000) class MessageOut(BaseModel): id: int room_id: int sender_id: int content: str sent_at: datetime class Config: arbitrary_types_allowed = True # ====================== # 分享相关 Schema # ====================== class ShareCreate(BaseModel): title: str = Field(..., min_length=1, max_length=200) content: str = Field(..., min_length=1) is_public: bool = True type: ShareType = ShareType.public ai_character_id: Optional[int] = None class ShareUpdate(BaseModel): title: Optional[str] = Field(None, min_length=1, max_length=200) content: Optional[str] = Field(None, min_length=1) is_public: Optional[bool] = None type: Optional[ShareType] = None ai_character_id: Optional[int] = None class CommentCreate(BaseModel): content: str = Field(..., min_length=1, max_length=1000) parent_id: Optional[int] = None class CommentOut(BaseModel): id: int share_id: int commenter_id: int parent_id: Optional[int] content: str created_at: datetime commenter: UserOut # 嵌套用户信息 replies: List["CommentOut"] = [] # 子评论(递归定义) class Config: arbitrary_types_allowed = True CommentOut.model_rebuild() # 解决递归引用问题 class ShareLikeOut(BaseModel): share_id: int user_id: int liked_at: datetime class Config: arbitrary_types_allowed = True class ShareOut(BaseModel): id: int title: str content: str author_id: int is_public: bool type: ShareType ai_character_id: Optional[int] view_count: int like_count: int comment_count: int created_at: datetime # 关联字段(非数据库字段,来自 JOIN 查询) author: UserOut ai_character: Optional[CharacterBase] = None comments: List[CommentOut] = [] likes: List[ShareLikeOut] = [] class Config: arbitrary_types_allowed = True # ====================== # 搜索相关 Schema # ====================== class SearchRecordOut(BaseModel): id: int keyword: str user_id: Optional[int] search_time: datetime class Config: arbitrary_types_allowed = True class HotKeyword(BaseModel): keyword: str count: int class RecommendationItem(ShareOut): """推荐项复用 Share 结构""" pass class RecommendationResponse(BaseModel): method_used: str recommended_count: int items: List[RecommendationItem] # ====================== # 统计相关 Schema # ====================== class UserRoleDistribution(BaseModel): user: int = 0 dept_admin: int = 0 admin: int = 0 class UserStatsResponse(BaseModel): total_user: int = 0 new_user: int = 0 role_distribution: UserRoleDistribution class AICharacterDistribution(BaseModel): model_config = {"extra": "allow"} # 动态键:character_id -> count # 示例: {1: 45, 2: 30} class ShareStatsResponse(BaseModel): total_share: int = 0 total_like: int = 0 total_comment: int = 0 ai_character_distribution: AICharacterDistribution # ====================== # 聊天相关 Schema # ====================== class ChatRequest(BaseModel): character_id: int = Field(..., ge=1) message: str = Field(..., min_length=1) @field_validator("message") def trim_message(cls, v): return v.strip() # ====================== # 分页通用结构 # ====================== class PaginatedResponse(BaseModel): total: int page: int size: int items: List[Any] class Config: arbitrary_types_allowed = True 统一一下两个模型的结构
11-09
# repositories/user_repo.py from typing import Dict, List, Optional from .base import BaseRepository from models import Department, User from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession class UserRepository(BaseRepository[User]): def __init__(self, db: AsyncSession): super().__init__(User, db) async def get_by_account(self, account: str) -> Optional[User]: stmt = select(User).where(User.account == account) result = await self.db.execute(stmt) return result.scalar_one_or_none() async def get_with_department(self, user_id: int) -> Optional[Dict]: stmt = select( User.id, User.account, User.role, User.department_id, User.created_at, func.coalesce(Department.name, "").label("dept_name") ).outerjoin(Department, User.department_id == Department.id)\ .where(User.id == user_id) result = await self.db.execute(stmt) row = result.fetchone() return dict(row._mapping) if row else None async def list_users(self, role: str = None, dept_id: int = None, skip: int = 0, limit: int = 10) -> tuple[int, List[User]]: stmt = select(User) count_stmt = select(func.count()).select_from(User) if role: stmt = stmt.where(User.role == role) count_stmt = count_stmt.where(User.role == role) if dept_id is not None: stmt = stmt.where(User.department_id == dept_id) count_stmt = count_stmt.where(User.department_id == dept_id) total = (await self.db.execute(count_stmt)).scalar() stmt = stmt.offset(skip).limit(limit).order_by(User.created_at.desc()) result = await self.db.execute(stmt) return total, result.scalars().all() # repositories/share_repo.py from typing import Dict, List, Optional from models import Share, User, Character from sqlalchemy import select, func, or_, and_ from sqlalchemy.ext.asyncio import AsyncSession class ShareRepository: def __init__(self, db: AsyncSession): self.db = db async def create_share(self, **data) -> Share: share = Share(**data) self.db.add(share) await self.db.flush() return share async def get_share_with_author(self, share_id: int) -> Optional[Dict]: stmt = select( Share, User.account.label("author_account"), User.department_id, Character.name.label("ai_char_name") ).join(User, Share.author_id == User.id)\ .outerjoin(Character, Share.ai_character_id == Character.id)\ .where(Share.id == share_id) result = await self.db.execute(stmt) row = result.fetchone() if not row: return None data = {k: getattr(row.Share, k) for k in Share.__table__.columns.keys()} data.update({ "author_account": row.author_account, "department_id": row.department_id, "ai_char_name": row.ai_char_name }) return data async def list_shares(self, is_public: bool = None, author_id: int = None, type: str = None, order_by: str = "created_at DESC", skip: int = 0, limit: int = 10) -> tuple[int, List[Dict]]: valid_orders = { "created_at DESC": Share.created_at.desc(), "created_at ASC": Share.created_at.asc(), "like_count DESC": Share.like_count.desc(), "view_count DESC": Share.view_count.desc() } order_clause = valid_orders.get(order_by, Share.created_at.desc()) stmt = select( Share, User.account.label("author_account"), Character.name.label("ai_char_name") ).join(User, Share.author_id == User.id)\ .outerjoin(Character, Share.ai_character_id == Character.id) count_stmt = select(func.count(Share.id)) filters = [] if is_public is not None: filters.append(Share.is_public == is_public) if author_id: filters.append(Share.author_id == author_id) if type: filters.append(Share.type == type) if filters: stmt = stmt.where(and_(*filters)) count_stmt = count_stmt.where(and_(*filters)) total = (await self.db.execute(count_stmt)).scalar() stmt = stmt.order_by(order_clause).offset(skip).limit(limit) result = await self.db.execute(stmt) rows = result.fetchall() data = [] for r in rows: d = {k: getattr(r.Share, k) for k in Share.__table__.columns.keys()} d["author_account"] = r.author_account d["ai_char_name"] = r.ai_char_name data.append(d) return total, data # repositories/room_repo.py from typing import Dict, List, Optional from models import Character, Room, RoomMember, User from sqlalchemy import select, func, exists from sqlalchemy.ext.asyncio import AsyncSession class RoomRepository: def __init__(self, db: AsyncSession): self.db = db async def create_room(self, **data) -> Room: room = Room(**data) self.db.add(room) await self.db.flush() return room async def get_room_with_creator(self, room_id: int) -> Optional[Dict]: stmt = select( Room.id, Room.name, Room.type, Room.description, Room.creator_id, Room.dept_id, Room.ai_character_id, Room.created_at, User.account.label("creator_account"), Character.name.label("ai_char_name"), ).select_from(Room)\ .join(User, Room.creator_id == User.id)\ .outerjoin(Character, Room.ai_character_id == Character.id)\ .where(Room.id == room_id) result = await self.db.execute(stmt) row = result.mappings().fetchone() return dict(row) if row else None async def list_rooms(self, type: str = None, dept_id: int = None, skip: int = 0, limit: int = 10) -> tuple[int, List[Dict]]: subquery = select(RoomMember.room_id).where(RoomMember.user_id == User.id).correlate(Room) stmt = select( Room.id, Room.name, Room.type, Room.description, Room.creator_id, User.account.label("creator_account"), Room.created_at, func.count(RoomMember.user_id).label("member_count") ).join(User, Room.creator_id == User.id)\ .outerjoin(RoomMember, Room.id == RoomMember.room_id) count_stmt = select(func.count(Room.id)) if type: stmt = stmt.where(Room.type == type) count_stmt = count_stmt.where(Room.type == type) if dept_id is not None: stmt = stmt.where(Room.dept_id == dept_id) count_stmt = count_stmt.where(Room.dept_id == dept_id) stmt = stmt.group_by(Room.id).order_by(Room.created_at.desc()).offset(skip).limit(limit) count = (await self.db.execute(count_stmt)).scalar() result = await self.db.execute(stmt) return count, [dict(r._mapping) for r in result.fetchall()] # repositories/base.py from typing import TypeVar, Generic, Optional, List, Dict, Any from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, update as sql_update, delete as sql_delete from sqlalchemy.orm import DeclarativeBase # 定义类型变量 ModelType = TypeVar("ModelType", bound=DeclarativeBase) # 所有 ORM 模型都继承自 DeclarativeBase class BaseRepository(Generic[ModelType]): def __init__(self, model: type[ModelType], db: AsyncSession): self.model = model self.db = db async def get_by_id(self, obj_id: int) -> Optional[ModelType]: stmt = select(self.model).where(self.model.id == obj_id) result = await self.db.execute(stmt) return result.scalar_one_or_none() async def get_all(self, skip: int = 0, limit: int = 100) -> List[ModelType]: stmt = select(self.model).offset(skip).limit(limit) result = await self.db.execute(stmt) return list(result.scalars().all()) async def create(self, **kwargs) -> ModelType: obj = self.model(**kwargs) self.db.add(obj) await self.db.flush() return obj async def update(self, obj_id: int, **updates) -> bool: stmt = sql_update(self.model).where(self.model.id == obj_id).values(**updates) result = await self.db.execute(stmt) return result.rowcount > 0 async def delete(self, obj_id: int) -> bool: stmt = sql_delete(self.model).where(self.model.id == obj_id) result = await self.db.execute(stmt) return result.rowcount > 0 # database.py import os from dotenv import load_dotenv from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker from typing import AsyncGenerator load_dotenv() DATABASE_URL = os.getenv( "DATABASE_URL", "mysql+asyncmy://root:123456@localhost/ai_roleplay?charset=utf8mb4" ) # 创建异步引擎 engine = create_async_engine( DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=10, max_overflow=20, pool_recycle=3600, ) # 异步 session 工厂 async_session = async_sessionmaker( bind=engine, class_=AsyncSession, expire_on_commit=False, autoflush=False ) # 依赖注入:获取数据库会话 async def get_db() -> AsyncGenerator[AsyncSession, None]: async with async_session() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close() # models.py - 所有数据库表的 ORM 映射 from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey, func from sqlalchemy.orm import declarative_base, relationship from datetime import datetime, timezone Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) account = Column(String(50), unique=True, index=True) password = Column(String(255)) role = Column(String(20), default="user") department_id = Column(Integer, ForeignKey("departments.id"), nullable=True) created_at = Column(DateTime, default=datetime.now(timezone.utc)) # 关系 department = relationship("Department", back_populates="users") rooms_created = relationship("Room", back_populates="creator") room_memberships = relationship("RoomMember", back_populates="user") shares = relationship("Share", back_populates="author") comments = relationship("Comment", back_populates="commenter") search_records = relationship("SearchRecord", back_populates="user") class Department(Base): __tablename__ = "departments" id = Column(Integer, primary_key=True, index=True) name = Column(String(50), unique=True) description = Column(Text) created_at = Column(DateTime, default=datetime.now(timezone.utc)) users = relationship("User", back_populates="department") rooms = relationship("Room", back_populates="department") class Room(Base): __tablename__ = "rooms" id = Column(Integer, primary_key=True, index=True) name = Column(String(100)) type = Column(String(20)) # public, private, department dept_id = Column(Integer, ForeignKey("departments.id"), nullable=True) ai_character_id = Column(Integer, ForeignKey("characters.id"), nullable=True) description = Column(Text) creator_id = Column(Integer, ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.now(timezone.utc)) creator = relationship("User", back_populates="rooms_created") department = relationship("Department", back_populates="rooms") ai_character = relationship("Character") members = relationship("RoomMember", back_populates="room", cascade="all, delete-orphan") messages = relationship("RoomMessage", back_populates="room", cascade="all, delete-orphan") class RoomMember(Base): __tablename__ = "room_members" id = Column(Integer, primary_key=True) room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) joined_at = Column(DateTime, default=datetime.now(timezone.utc)) room = relationship("Room", back_populates="members") user = relationship("User", back_populates="room_memberships") class RoomMessage(Base): __tablename__ = "room_messages" id = Column(Integer, primary_key=True) room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False) sender_id = Column(Integer, ForeignKey("users.id"), nullable=False) content = Column(Text, nullable=False) sent_at = Column(DateTime, default=datetime.now(timezone.utc)) room = relationship("Room", back_populates="messages") sender = relationship("User") class Character(Base): __tablename__ = "characters" id = Column(Integer, primary_key=True, index=True) name = Column(String(50)) trait = Column(Text) avatar_url = Column(String(255)) created_at = Column(DateTime, default=datetime.now(timezone.utc)) shares = relationship("Share", back_populates="ai_character") conversations = relationship("UserConversation", back_populates="character") class Share(Base): __tablename__ = "shares" id = Column(Integer, primary_key=True, index=True) title = Column(String(200)) content = Column(Text) author_id = Column(Integer, ForeignKey("users.id")) is_public = Column(Boolean, default=True) type = Column(String(20)) # public, draft, private ai_character_id = Column(Integer, ForeignKey("characters.id"), nullable=True) view_count = Column(Integer, default=0) like_count = Column(Integer, default=0) comment_count = Column(Integer, default=0) created_at = Column(DateTime, default=datetime.now(timezone.utc)) author = relationship("User", back_populates="shares") ai_character = relationship("Character", back_populates="shares") likes = relationship("ShareLike", back_populates="share", cascade="all, delete-orphan") comments = relationship("Comment", back_populates="share", cascade="all, delete-orphan") class ShareLike(Base): __tablename__ = "share_likes" id = Column(Integer, primary_key=True) share_id = Column(Integer, ForeignKey("shares.id"), nullable=False) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime, default=datetime.now(timezone.utc)) share = relationship("Share", back_populates="likes") user = relationship("User") class Comment(Base): __tablename__ = "comments" id = Column(Integer, primary_key=True) share_id = Column(Integer, ForeignKey("shares.id"), nullable=False) commenter_id = Column(Integer, ForeignKey("users.id"), nullable=False) content = Column(Text, nullable=False) parent_id = Column(Integer, ForeignKey("comments.id"), nullable=True) created_at = Column(DateTime, default=datetime.now(timezone.utc)) share = relationship("Share", back_populates="comments") commenter = relationship("User", back_populates="comments") replies = relationship("Comment", backref="parent", remote_side=[id]) class SearchRecord(Base): __tablename__ = "search_records" id = Column(Integer, primary_key=True) keyword = Column(String(100), index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=True) search_time = Column(DateTime, default=datetime.now(timezone.utc)) user = relationship("User", back_populates="search_records") class UserConversation(Base): __tablename__ = "user_conversations" id = Column(Integer, primary_key=True) user_id = Column(Integer, nullable=False, index=True) character_id = Column(Integer, ForeignKey("characters.id")) user_message = Column(Text, nullable=False) ai_message = Column(Text, nullable=False) timestamp = Column(DateTime, default=datetime.now(timezone.utc)) character = relationship("Character", back_populates="conversations") 最后检查数据库模块内容,看一下结构有没有问题
11-08
from datetime import datetime, timezone from typing import Optional, Type from sqlmodel import SQLModel, Field from sqlalchemy import Column, Text, DateTime, func import re # 缓存已创建的模型 _conversation_models: dict[str, Type[SQLModel]] = {} def is_valid_table_name(table_name: str) -> bool: """验证表名是否符合安全规范""" return re.match(r'^conversations_\d+$', table_name) is not None def get_conversation_model(user_id: int) -> Type[SQLModel]: """动态创建用户的对话模型 参数: user_id: 用户唯一ID 返回: 动态生成的SQLModel类 """ table_name = f"conversations_{user_id}" # 验证表名安全性 if not is_valid_table_name(table_name): raise ValueError(f"Invalid table name format: {table_name}") # 返回缓存模型(如果已存在) if table_name in _conversation_models: return _conversation_models[table_name] class Conversation(SQLModel, table=True): __tablename__ = table_name id: Optional[int] = Field(default=None, primary_key=True) character_id: int = Field(foreign_key="characters.id") user_message: str = Field(sa_column=Column(Text)) ai_message: str = Field(sa_column=Column(Text)) timestamp: datetime = Field( default_factory=lambda: datetime.now(timezone.utc), sa_column=Column(DateTime(timezone=True), server_default=func.now()) ) # 设置元数据 model_name = f"Conversation_{user_id}" Conversation.__name__ = model_name Conversation.__qualname__ = model_name # 添加到缓存 _conversation_models[table_name] = Conversation return Conversation 这种动态生成的表怎么办
最新发布
11-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值