TRM-coding | d1cbf67 | 2025-06-18 15:15:08 +0800 | [diff] [blame^] | 1 | from .users import User |
| 2 | from . import Base |
| 3 | |
| 4 | from sqlalchemy import ( |
| 5 | Column, Integer, String, Text, JSON, Enum, |
| 6 | TIMESTAMP, ForeignKey, Index, func, text |
| 7 | ) |
| 8 | from sqlalchemy.ext.declarative import declarative_base |
| 9 | from sqlalchemy.orm import relationship |
| 10 | |
| 11 | |
| 12 | class Post(Base): |
| 13 | __tablename__ = 'posts' |
| 14 | __table_args__ = ( |
| 15 | # 索引 |
| 16 | Index('idx_posts_heat', 'heat'), |
| 17 | # MySQL 引擎、字符集、校对规则、表注释 |
| 18 | { |
| 19 | 'mysql_engine': 'InnoDB', |
| 20 | 'mysql_charset': 'utf8mb4', |
| 21 | 'mysql_collate': 'utf8mb4_general_ci', |
| 22 | 'comment': '内容帖子表' |
| 23 | } |
| 24 | ) |
| 25 | |
| 26 | def to_dict(self): |
| 27 | return { |
| 28 | 'id': self.id if self.id else None, |
| 29 | 'user_id': self.user_id if self.user_id else None, |
| 30 | 'topic_id': self.topic_id if self.topic_id else None, |
| 31 | 'type': self.type if self.type else None, |
| 32 | 'title': self.title if self.title else None, |
| 33 | 'content': self.content if self.content else None, |
| 34 | 'media_urls': self.media_urls if self.media_urls else None, |
| 35 | 'status': self.status if self.status else None, |
| 36 | 'heat': self.heat if self.heat else None, |
| 37 | 'created_at': self.created_at.isoformat() if self.created_at else None, |
| 38 | 'updated_at': self.updated_at.isoformat() if self.updated_at else None |
| 39 | } |
| 40 | |
| 41 | |
| 42 | id = Column( |
| 43 | Integer, |
| 44 | primary_key=True, |
| 45 | autoincrement=True, |
| 46 | comment='帖子ID' |
| 47 | ) |
| 48 | user_id = Column( |
| 49 | Integer, |
| 50 | ForeignKey('users.id', ondelete='CASCADE'), |
| 51 | nullable=False, |
| 52 | index=True, |
| 53 | comment='作者ID' |
| 54 | ) |
| 55 | topic_id = Column( |
| 56 | Integer, |
| 57 | ForeignKey('topics.id', ondelete='SET NULL'), |
| 58 | nullable=True, |
| 59 | index=True, |
| 60 | comment='所属话题ID' |
| 61 | ) |
| 62 | type = Column( |
| 63 | Enum('text', 'image', 'video', 'document', name='post_type'), |
| 64 | nullable=False, |
| 65 | server_default=text("'text'"), |
| 66 | comment='内容类型' |
| 67 | ) |
| 68 | title = Column( |
| 69 | String(255), |
| 70 | nullable=False, |
| 71 | comment='标题' |
| 72 | ) |
| 73 | content = Column( |
| 74 | Text, |
| 75 | nullable=False, |
| 76 | comment='正文内容' |
| 77 | ) |
| 78 | media_urls = Column( |
| 79 | JSON, |
| 80 | nullable=True, |
| 81 | comment='媒体资源URL数组' |
| 82 | ) |
| 83 | status = Column( |
| 84 | Enum('draft', 'pending', 'published', 'deleted', 'rejected', name='post_status'), |
| 85 | nullable=False, |
| 86 | server_default=text("'draft'"), |
| 87 | comment='状态' |
| 88 | ) |
| 89 | heat = Column( |
| 90 | Integer, |
| 91 | nullable=False, |
| 92 | server_default=text('0'), |
| 93 | comment='热度值' |
| 94 | ) |
| 95 | created_at = Column( |
| 96 | TIMESTAMP, |
| 97 | nullable=True, |
| 98 | server_default=func.current_timestamp(), |
| 99 | comment='创建时间' |
| 100 | ) |
| 101 | updated_at = Column( |
| 102 | TIMESTAMP, |
| 103 | nullable=True, |
| 104 | server_default=func.current_timestamp(), |
| 105 | onupdate=func.current_timestamp(), |
| 106 | comment='更新时间' |
| 107 | ) |
| 108 | |
| 109 | # 可选:与 User/Topic 模型的关系(需要在 User、Topic 中也定义 back_populates) |
| 110 | # user = relationship('User', back_populates='posts') |
| 111 | # topic = relationship('Topic', back_populates='posts') |