from sqlalchemy import (BigInteger, Boolean, Column, Integer, DECIMAL, String, LargeBinary) from sqlalchemy.orm import relationship from models.base import AuditBase, IdBase class Blog(AuditBase): title = Column(String(255), nullable=False, comment="博客标题") top_value = Column(Integer, nullable=False, default=0, comment="置顶值 越大越靠前") is_great = Column(Boolean, nullable=False, default=False, comment="是否是精品") category_id = Column(BigInteger, nullable=False, comment="博客类别") summary = Column(String(255), nullable=False, comment="博客内容概要") content_id = Column(BigInteger, nullable=False, comment="博客内容") word_count = Column(Integer, nullable=False, default=0, comment="字数统计") read_duration = Column(DECIMAL(10, 2), nullable=False, default=0.00, comment="阅读时长") is_approved = Column(Boolean, nullable=False, default=False, comment="是否发布") # 分类关系(多对一) category = relationship( "BlogCategory", # 与BlogCategory的blogs属性建立双向关系 back_populates="blogs", # 只级联保存和合并操作,不级联删除(删除博客不应删除分类 cascade="save-update, merge", # 明确指定连接条件 # 如果数据库设置了外键可以省略 primaryjoin="foreign(Blog.category_id) == BlogCategory.id" ) # 内容关系(一对一) content = relationship( "BlogContent", # 与BlogContent的blog属性建立双向关系 back_populates="blog", # 完全级联操作:保存、合并、刷新、删除等所有操作都会级联 cascade="all, delete-orphan", # 设置为False表示一对一关系,返回单个对象而不是列表 uselist=False, # 确保内容只有一个父博客,与delete-orphan配合使用 single_parent=True, # 明确指定连接条件 primaryjoin="foreign(Blog.content_id) == BlogContent.id" ) # 访问记录(一对多) visits = relationship( "BlogVisit", # 与BlogVisit的blog属性建立双向关系 back_populates="blog", # 完全级联操作:博客删除时自动删除所有访问记录 cascade="all, delete-orphan", # 明确指定连接条件 primaryjoin="Blog.id == foreign(BlogVisit.blog_id)" ) # 4. 评论(一对多) comments = relationship( "BlogComment", # 与BlogComment的blog属性建立双向关系 back_populates="blog", # 完全级联操作:博客删除时自动删除所有评论 cascade="all, delete-orphan", # 明确指定连接条件 primaryjoin="Blog.id == foreign(BlogComment.blog_id)" ) class BlogCategory(AuditBase): name = Column(String(45), nullable=False, comment="类别名称") blogs = relationship( "Blog", # 与Blog的category属性建立双向关系 back_populates="category", # 完全级联操作:分类删除时自动删除所有关联的博客 # 警告:这会级联删除分类下的所有博客,包括博客的内容、访问记录和评论 cascade="all, delete-orphan", # 明确指定连接条件 primaryjoin="BlogCategory.id == foreign(Blog.category_id)" ) class BlogContent(IdBase): content = Column(LargeBinary, nullable=False, comment="博客内容") blog = relationship( "Blog", # 与Blog的content属性建立双向关系 back_populates="content", # 设置为False表示一对一关系 uselist=False, # 明确指定连接条件 primaryjoin="BlogContent.id == foreign(Blog.content_id)" ) class BlogVisit(AuditBase): ip = Column(String(255), nullable=False, comment="IP地址") os = Column(String(255), nullable=False, comment="操作系统") browser = Column(String(255), nullable=False, comment="浏览器") uri = Column(String(255), nullable=False, comment="路径") blog_id = Column(BigInteger, nullable=True, comment="博客ID") blog = relationship( "Blog", # 与Blog的visits属性建立双向关系 back_populates="visits", # 明确指定连接条件 primaryjoin="foreign(BlogVisit.blog_id) == Blog.id" ) class BlogComment(AuditBase): blog_id = Column(BigInteger, nullable=False, comment="博客ID") parent_id = Column(BigInteger, nullable=False, comment="父评论ID") name = Column(String(255), nullable=False, comment="评论人昵称") website = Column(String(255), nullable=True, comment="评论人网站") ip_address = Column(String(45), nullable=False, comment="评论人IP") user_agent = Column(String(255), nullable=False, comment="评论人浏览器信息") content = Column(String(255), nullable=False, comment="评论内容") is_approved = Column(Boolean, nullable=False, default=False, comment="是否通过") blog = relationship( "Blog", # 与Blog的comments属性建立双向关系 back_populates="comments", # 明确指定连接条件 primaryjoin="foreign(BlogComment.blog_id) == Blog.id" )