-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
122 lines (98 loc) · 4.8 KB
/
models.py
File metadata and controls
122 lines (98 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from datetime import datetime
import re
import markdown
db = SQLAlchemy()
# 文章与标签的多对多关联表
article_tags = db.Table('article_tags',
db.Column('article_id', db.Integer, db.ForeignKey('article.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(256), nullable=False)
nickname = db.Column(db.String(50)) # 昵称
gender = db.Column(db.String(10)) # 性别
repo_link = db.Column(db.String(200)) # 个人代码仓库链接
bio = db.Column(db.Text) # 个人简介
avatar_url = db.Column(db.String(200), default='https://api.dicebear.com/9.x/croodles/svg?seed=Jessica') # 默认头像
last_login = db.Column(db.DateTime)
# 关联
articles = db.relationship('Article', backref='author', lazy=True)
categories = db.relationship('Category', backref='owner', lazy=True)
tags = db.relationship('Tag', backref='owner', lazy=True)
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
summary = db.Column(db.Text)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
is_draft = db.Column(db.Boolean, default=False) # 新增:是否为草稿
update_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
cover_url = db.Column(db.String(256))
category = db.relationship('Category', backref='posts')
tags = db.relationship('Tag', secondary=article_tags, backref=db.backref('articles', lazy='dynamic'))
comments = db.relationship('Comment', backref='target_article', lazy=True, cascade="all, delete-orphan")
@property
def word_count(self):
"""计算去除 Markdown 符号后的纯文字字数"""
if not self.content:
return 0
# 1. 拷贝一份正文内容进行清理
text = self.content
# 2. 正则过滤逻辑
# 去掉代码块 (```...```)
text = re.sub(r'```.*?```', '', text, flags=re.DOTALL)
# 去掉图片 ()
text = re.sub(r'!\[.*?\]\(.*?\)', '', text)
# 去掉链接,只保留链接文字 ([text](url) -> text)
text = re.sub(r'\[(.*?)\]\(.*?\)', r'\1', text)
# 去掉标题符号 (# ## ###)
text = re.sub(r'#+\s?', '', text)
# 去掉粗体、斜体 (** * __ _)
text = re.sub(r'(\*\*|__|[\*_])', '', text)
# 去掉列表符号 (- * + 1. 2.)
text = re.sub(r'^\s*[\->\*+]\s+', '', text, flags=re.MULTILINE)
text = re.sub(r'^\s*\d+\.\s+', '', text, flags=re.MULTILINE)
# 去掉 HTML 标签
text = re.sub(r'<[^>]*>', '', text)
# 去掉多余的换行和空格
text = "".join(text.split())
return len(text)
@property
def read_time(self):
"""估算阅读时间"""
count = self.word_count
# 中文阅读速度通常为 300-500 字/分钟
minutes = round(count / 400)
return minutes if minutes > 0 else 1
@property
def content_html(self):
"""后端预渲染:将 Markdown 转为 HTML"""
if self.content:
# 开启常用的 Markdown 扩展:表格、代码高亮、目录、自动链接
exts = ['markdown.extensions.extra', 'markdown.extensions.codehilite',
'markdown.extensions.toc', 'markdown.extensions.fenced_code']
return markdown.markdown(self.content, extensions=exts)
return ""
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.now) # 评论时间
# 外键关联
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
article_id = db.Column(db.Integer, db.ForeignKey('article.id'), nullable=False)
# 为了方便查询,给 Article 和 User 反向建立关系
# 这样可以用 article.comments 拿到所有评论
author = db.relationship('User', backref=db.backref('comments', lazy=True))