Files
mokeeText/backend/models.py
2026-07-15 16:08:17 +08:00

136 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""SQLAlchemy 数据模型"""
from datetime import datetime
from sqlalchemy import (
create_engine, Column, Integer, String, Text, DateTime, LargeBinary,
Enum as SAEnum, ForeignKey, Table
)
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
from config import get_db_url
engine = create_engine(get_db_url(), echo=False, pool_pre_ping=True)
SessionLocal = sessionmaker(bind=engine, autocommit=False)
Base = declarative_base()
def get_db():
"""获取数据库会话FastAPI 依赖注入)"""
db = SessionLocal()
try:
yield db
finally:
db.close()
# ===== 文件夹 =====
class Folder(Base):
"""文件夹表 — 笔记和网站共用"""
__tablename__ = "folders"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(100), nullable=False)
type = Column(SAEnum("note", "website", name="folder_type"), nullable=False, default="note")
parent_id = Column(Integer, ForeignKey("folders.id"), nullable=True)
sort_order = Column(Integer, default=0)
created_by = Column(String(100), nullable=False, default="admin")
created_at = Column(DateTime, default=datetime.utcnow)
children = relationship("Folder", backref="parent", remote_side=[id])
notes = relationship("Note", back_populates="folder", cascade="all, delete-orphan")
websites = relationship("Website", back_populates="folder", cascade="all, delete-orphan")
# ===== 笔记 =====
class Note(Base):
"""笔记表"""
__tablename__ = "notes"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(500), nullable=False, default="无标题")
content = Column(Text, nullable=True) # Tiptap 输出的 HTML
folder_id = Column(Integer, ForeignKey("folders.id"), nullable=True)
created_by = Column(String(100), nullable=False, default="admin")
updated_by = Column(String(100), nullable=False, default="admin")
share_token = Column(String(64), nullable=True, unique=True)
share_expires_at = Column(DateTime, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
folder = relationship("Folder", back_populates="notes")
tags = relationship("Tag", secondary="note_tags", back_populates="notes")
# ===== 笔记-标签关联 =====
note_tags = Table(
"note_tags",
Base.metadata,
Column("note_id", Integer, ForeignKey("notes.id", ondelete="CASCADE"), primary_key=True),
Column("tag_id", Integer, ForeignKey("tags.id", ondelete="CASCADE"), primary_key=True),
)
# ===== 标签 =====
class Tag(Base):
"""标签表"""
__tablename__ = "tags"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False, unique=True)
color = Column(String(20), default="#666666")
notes = relationship("Note", secondary="note_tags", back_populates="tags")
# ===== 网站 =====
class Website(Base):
"""网站表"""
__tablename__ = "websites"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(200), nullable=False)
url = Column(String(500), nullable=False)
folder_id = Column(Integer, ForeignKey("folders.id"), nullable=True)
created_by = Column(String(100), nullable=False, default="admin")
updated_by = Column(String(100), nullable=False, default="admin")
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
folder = relationship("Folder", back_populates="websites")
accounts = relationship("Account", back_populates="website", cascade="all, delete-orphan",
order_by="Account.sort_order")
# ===== 账号 =====
class Account(Base):
"""账号表 — 存储网站登录凭据"""
__tablename__ = "accounts"
id = Column(Integer, primary_key=True, autoincrement=True)
website_id = Column(Integer, ForeignKey("websites.id", ondelete="CASCADE"), nullable=False)
username = Column(String(500), nullable=False)
password = Column(String(500), nullable=False) # 明文存储,后续加密
remark = Column(Text, nullable=True)
created_by = Column(String(100), nullable=False, default="admin")
updated_by = Column(String(100), nullable=False, default="admin")
sort_order = Column(Integer, default=0)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
website = relationship("Website", back_populates="accounts")
# ===== 上传文件 =====
class Upload(Base):
"""文件上传表 — 图片存储(新文件存文件服务,旧文件兼容 DB blob"""
__tablename__ = "uploads"
id = Column(Integer, primary_key=True, autoincrement=True)
filename = Column(String(255), nullable=False)
content_type = Column(String(100), nullable=False)
data = Column(LargeBinary(length=2**32-1), nullable=True) # 旧图片 LONGBLOB兼容新文件为 NULL
file_id = Column(String(64), nullable=True) # 文件服务返回的 fileId新文件
size = Column(Integer, default=0)
created_by = Column(String(100), nullable=False, default="admin")
created_at = Column(DateTime, default=datetime.utcnow)