这个基于Flask+Vue的博客系统是一个典型的全栈开发项目,采用了前后端分离的架构设计。作为一名有多年开发经验的工程师,我认为这种技术组合非常适合中小型Web应用的快速开发。Flask作为Python轻量级框架,提供了足够的灵活性;而Vue.js作为前端框架,能够很好地处理复杂的用户交互。
这个系统不仅实现了博客的基本功能(文章发布、评论、用户管理等),还包含了完整的后台管理系统,可以满足从个人博客到小型内容管理系统的各种需求。特别值得一提的是,项目采用了RESTful API设计风格,前后端通过JSON格式进行数据交互,这种架构在现代Web开发中已经成为主流。
后端采用Flask框架,这是一个用Python编写的轻量级Web应用框架。选择Flask而非Django的主要考虑是:
核心使用的Flask扩展包括:
数据库选用MySQL,主要考虑到:
前端采用Vue.js框架,配合以下技术栈:
选择Vue而非React或Angular的主要原因是:
系统采用典型的前后端分离架构:
code复制客户端浏览器 (Vue.js)
↑↓ HTTP/HTTPS
API服务器 (Flask)
↑↓ SQL
数据库 (MySQL)
这种架构的优势在于:
用户认证采用JWT(JSON Web Token)机制,流程如下:
关键代码示例(Flask端):
python复制from flask_jwt_extended import create_access_token, jwt_required
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username')
password = request.json.get('password')
user = User.query.filter_by(username=username).first()
if not user or not user.check_password(password):
return jsonify({"msg": "Bad credentials"}), 401
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
return jsonify({"msg": "访问成功"})
前端处理(Vue.js):
javascript复制// 登录
axios.post('/api/login', {
username: 'test',
password: '123456'
}).then(response => {
localStorage.setItem('token', response.data.access_token)
})
// 受保护请求
axios.get('/api/protected', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
})
文章模块实现了CRUD操作,核心设计包括:
python复制class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
author = db.relationship('User', backref='articles')
评论功能采用树形结构设计,支持回复:
python复制class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
article_id = db.Column(db.Integer, db.ForeignKey('article.id'))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
parent_id = db.Column(db.Integer, db.ForeignKey('comment.id'))
article = db.relationship('Article', backref='comments')
user = db.relationship('User', backref='comments')
replies = db.relationship('Comment', backref=db.backref('parent', remote_side=[id]))
前端渲染时需要注意递归组件实现嵌套评论显示。
sql复制CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password_hash` varchar(128) NOT NULL,
`email` varchar(120) NOT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
sql复制CREATE TABLE `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`content` text NOT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `articles_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
sql复制CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` text NOT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`article_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `article_id` (`article_id`),
KEY `user_id` (`user_id`),
KEY `parent_id` (`parent_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`article_id`) REFERENCES `articles` (`id`),
CONSTRAINT `comments_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
CONSTRAINT `comments_ibfk_3` FOREIGN KEY (`parent_id`) REFERENCES `comments` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
避免过度索引,特别是在写多读少的表上
使用EXPLAIN分析查询性能
bash复制# 创建虚拟环境
python -m venv venv
# 激活环境
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
bash复制# 安装Node.js和npm
# 然后安装项目依赖
npm install
# 开发模式运行
npm run serve
推荐使用Docker容器化部署:
dockerfile复制FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "-w 4", "-b :5000", "app:app"]
yaml复制version: '3'
services:
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- DATABASE_URL=mysql://dbuser:dbpass@mysql/blog
depends_on:
- mysql
frontend:
build: ./frontend
ports:
- "8080:80"
depends_on:
- backend
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=blog
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=dbpass
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
bash复制# 构建镜像
docker-compose build
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f
前后端分离开发时常见的跨域问题解决方案:
python复制from flask_cors import CORS
app = Flask(__name__)
CORS(app)
python复制CORS(app, resources={
r"/api/*": {
"origins": ["http://localhost:8080"],
"methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
这个博客系统可以进一步扩展为:
在开发这个项目的过程中,我总结了以下几点经验:
这个博客系统虽然基础,但涵盖了现代Web开发的许多核心概念和技术。通过这个项目,开发者可以掌握前后端分离开发的全流程,为更复杂的项目打下坚实基础。