class Comment(db.Model): id = db.Column(db.Integer, primary_key=True) author = db.Column(db.String(30)) email = db.Column(db.String(254)) # 评论者的邮箱 site = db.Column(db.String(255)) body = db.Column(db.Text) # 某条评论是否来自管理员 from_admin = db.Column(db.Boolean, default=False) # 某条评论是否通过审核 reviewed = db.Column(db.Boolean, default=False) timestamp = db.Column(db.DateTime, default=datetime.utcnow, index=True) # 对应的文章,外键, 参数为[表名.列名] post_id = db.Column(db.Integer, db.ForeignKey("post.id")) post = db.relationship("Post", back_populates="commments") # 被回复的评论 replied_id = db.Column(db.Integer, db.ForeignKey("comment.id")) replied = db.relationship("Comment", back_populates="replies", remote_side=[id]) # 一条评论对应多条回复 replies = db.relationship("Comment", back_populates="replied", cascade="all")
class Post(db.Model): id = db.Column(db.Integer, primary_key=True) # id 主键 title = db.Column(db.String(60)) body = db.Column(db.Text) timestamp = db.Column(db.DateTime, default=datetime.utcnow, index=True) can_comment = db.Column(db.Boolean, default=True) # 文章是否可以评论 # 和评论是一对多关系 # 第一个参数是另一张表在模型文件中定义的类名,back_populates定义的反向关系, # 第三个是数据库级联操作(一定是在一对多中的一这边设置级联) commments = db.relationship("Comment", back_populates="post", cascade="all,delete-orphan") # 文章分类和文章是一对多关系 category_id = db.Column(db.Integer, db.ForeignKey("category.id")) category = db.relationship('Category', back_populates='posts')
class Category(db.Model): __tablename__ = 'category' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(64), unique=True, index=True) name = db.Column(db.String(64), unique=True, index=True) desp = db.Column(db.String(300)) articles = db.relationship('Article', backref='category', lazy='dynamic') def __repr__(self): return '<Name %r>' % self.name
class Category(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30), unique=True) posts = db.relationship('Post', back_populates='category') def delete(self): # 第一类作为默认分类 default_category = Category.query.get(1) # 当某一类别被删除时,其之前所对应的文章全部被归为默认分类 posts = self.posts[:] for p in posts: p.category = default_category db.session.delete(self) db.session.commit()
class User(UserMixin, db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(64), unique=True, index=True) password_hash = db.Column(db.String(128)) member_since = db.Column(db.DateTime(), default=datetime.utcnow) last_seen = db.Column(db.DateTime(), default=datetime.utcnow) status = db.Column(db.Boolean, default=False) role = db.Column(db.Boolean, default=False) articles = db.relationship('Article', backref='author', lazy='dynamic') is_super_administrator = db.Column(db.Boolean, default=False) # 是否是超级管理员 @property def password(self): raise ArithmeticError('非明文密码,不可读。') @password.setter def password(self, password): self.password_hash = generate_password_hash(password=password) def verify_password(self, password): return check_password_hash(self.password_hash, password=password) def is_admin(self): return self.role def ping(self): self.last_seen = datetime.utcnow() db.session.add(self) def is_author(self): return Article.query.filter_by(author_id=self.id).first() def __repr__(self): return '<User %r>' % self.username
class Article(db.Model): __tablename__ = 'article' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(120), index=True) name = db.Column(db.String(64), index=True, unique=True) content = db.Column(db.Text) content_html = db.Column(db.Text) summary = db.Column(db.String(300)) thumbnail = db.Column(db.String(200)) state = db.Column(db.Integer, default=0) vc = db.Column(db.Integer, default=0) timestamp = db.Column(db.DateTime, index=True, default=datetime.now) # 是否是轮播图文章,默认不是。 is_Rotation = db.Column(db.Boolean, default=False) author_id = db.Column(db.Integer, db.ForeignKey('user.id')) category_id = db.Column(db.Integer, db.ForeignKey('category.id')) tags = db.relationship('Tag', secondary=article_tag, backref=db.backref('articles', lazy='dynamic'), lazy='dynamic') def content_to_html(self): return markdown.markdown(self.content, extensions=[ 'markdown.extensions.extra', 'markdown.extensions.codehilite', ]) @property def author(self): """返回作者对象""" return User.query.get(self.author_id) @property def category(self): """返回文章分类对象""" return Category.query.get(self.category_id) @property def category_name(self): """返回文章分类名称,主要是为了使用 flask-wtf 的 obj 返回对象的功能""" return Category.query.get(self.category_id).name @property def previous(self): """用于分页显示的上一页""" a = self.query.filter(Article.state==1,Article.id < self.id). \ order_by(Article.timestamp.desc()).first() return a @property def next(self): """用于分页显示的下一页""" a = self.query.filter(Article.state==1,Article.id > self.id). \ order_by(Article.timestamp.asc()).first() return a @property def tag_names(self): """返回文章的标签的字符串,用英文‘, ’分隔,主要用于修改文章功能""" tags = [] for tag in self.tags: tags.append(tag.name) return ', '.join(tags) @property def thread_key(self): # 用于评论插件 return hashlib.new(name='md5', string=str(self.id)).hexdigest() def __repr__(self): return '<Title %r>' % self.title