一、准备工作:安装必要工具和库¶
在开始前,确保你已经安装了Python(推荐3.6+版本)。打开终端,执行以下命令安装Flask及相关扩展:
pip install flask flask-sqlalchemy flask-login flask-wtf flask-bootstrap
- Flask:核心Web框架
- Flask-SQLAlchemy:ORM工具,简化数据库操作
- Flask-Login:用户认证管理
- Flask-WTF:表单处理与验证
- Flask-Bootstrap:快速美化页面(基于Bootstrap)
二、项目初始化:搭建目录结构¶
创建博客项目文件夹,并按以下结构组织文件:
blog_project/
├── app.py # 主程序入口
├── config.py # 配置文件(可选,本教程简化)
├── models.py # 数据库模型定义
├── templates/ # HTML模板文件
│ ├── base.html # 基础模板(导航、页脚等)
│ ├── index.html # 首页
│ ├── post_detail.html # 文章详情页
│ └── create_post.html # 写文章页面
└── static/ # 静态资源(CSS、JS等)
三、数据库设计:定义数据模型¶
在models.py中定义用户和文章的数据库模型:
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
db = SQLAlchemy() # 初始化SQLAlchemy
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
password_hash = db.Column(db.String(128), nullable=False)
# 关联文章(一个用户可写多篇文章)
posts = db.relationship('Post', backref='author', lazy=True)
# 密码加密存储
def set_password(self, password):
self.password_hash = generate_password_hash(password)
# 验证密码
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) # 外键关联用户
四、应用初始化:配置与核心组件¶
在app.py中初始化Flask应用,配置数据库和扩展:
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired
from models import db, User, Post
from flask_bootstrap import Bootstrap
# 初始化Flask应用
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here' # 用于加密会话(开发时用随机字符串)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' # SQLite数据库
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 关闭不必要的跟踪
# 初始化扩展
db.init_app(app)
Bootstrap(app) # 启用Bootstrap美化
# 初始化登录管理
login_manager = LoginManager(app)
login_manager.login_view = 'login' # 未登录时跳转的页面
# 用户加载回调(Flask-Login必填)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# 创建数据库表(首次运行时执行)
with app.app_context():
db.create_all()
五、核心功能实现:路由与视图¶
下面实现博客的核心功能:首页文章列表、文章详情、写文章、用户登录。
1. 首页:展示所有文章¶
在app.py中添加首页路由:
@app.route('/')
def index():
# 查询所有文章,按时间倒序排列
posts = Post.query.order_by(Post.timestamp.desc()).all()
return render_template('index.html', posts=posts)
2. 文章详情页:展示单篇文章¶
按文章ID查询并展示单篇文章:
@app.route('/post/<int:post_id>')
def post_detail(post_id):
post = Post.query.get_or_404(post_id) # 若文章不存在返回404
return render_template('post_detail.html', post=post)
3. 写文章:表单提交与保存¶
使用Flask-WTF定义文章表单,处理用户输入:
# 定义文章表单
class PostForm(FlaskForm):
title = StringField('标题', validators=[DataRequired()])
content = TextAreaField('内容', validators=[DataRequired()])
submit = SubmitField('发布')
@app.route('/create', methods=['GET', 'POST'])
@login_required # 仅登录用户可访问
def create_post():
form = PostForm()
if form.validate_on_submit():
# 创建新文章并关联当前用户
post = Post(
title=form.title.data,
content=form.content.data,
author_id=current_user.id # 作者为当前登录用户
)
db.session.add(post)
db.session.commit()
flash('文章发布成功!', 'success')
return redirect(url_for('index')) # 发布后跳转首页
return render_template('create_post.html', form=form)
4. 用户登录与登出¶
使用Flask-Login实现用户认证:
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated: # 若已登录,直接跳转首页
return redirect(url_for('index'))
form = LoginForm() # 需定义LoginForm(此处省略,代码见下方)
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and user.check_password(form.password.data):
login_user(user) # 登录用户
return redirect(url_for('index'))
else:
flash('用户名或密码错误', 'danger')
return render_template('login.html', form=form)
@app.route('/logout')
@login_required
def logout():
logout_user() # 登出用户
flash('已成功登出', 'info')
return redirect(url_for('index'))
补充:LoginForm定义(在app.py中):
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired()])
password = StringField('密码', validators=[DataRequired()])
submit = SubmitField('登录')
六、模板渲染:用Bootstrap美化页面¶
创建templates/base.html作为基础模板,其他页面继承此模板:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}个人博客{% endblock %}</title>
<!-- 引入Bootstrap -->
{{ bootstrap.load_css() }}
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-default">
<div class="container">
<a class="navbar-brand" href="{{ url_for('index') }}">我的博客</a>
<ul class="nav navbar-nav navbar-right">
<li><a href="{{ url_for('index') }}">首页</a></li>
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('create_post') }}">写文章</a></li>
<li><a href="{{ url_for('logout') }}">登出</a></li>
{% else %}
<li><a href="{{ url_for('login') }}">登录</a></li>
{% endif %}
</ul>
</div>
</nav>
<!-- 内容区域 -->
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<!-- 页脚 -->
<div class="navbar navbar-default navbar-fixed-bottom text-center">
<div class="container">
<p class="text-muted">© 2023 个人博客系统</p>
</div>
</div>
{{ bootstrap.load_js() }}
</body>
</html>
1. 首页模板templates/index.html¶
{% extends "base.html" %}
{% block title %}首页 - 我的博客{% endblock %}
{% block content %}
<h2 class="text-center">最新文章</h2>
{% for post in posts %}
<div class="panel panel-default">
<div class="panel-body">
<h3><a href="{{ url_for('post_detail', post_id=post.id) }}">{{ post.title }}</a></h3>
<p class="text-muted">作者: {{ post.author.username }} | 发布时间: {{ post.timestamp.strftime('%Y-%m-%d %H:%M') }}</p>
<p>{{ post.content[:100] }}... <a href="{{ url_for('post_detail', post_id=post.id) }}">阅读全文</a></p>
</div>
</div>
{% endfor %}
{% endblock %}
2. 文章详情模板templates/post_detail.html¶
{% extends "base.html" %}
{% block title %}{{ post.title }} - 我的博客{% endblock %}
{% block content %}
<h2 class="text-center">{{ post.title }}</h2>
<p class="text-muted">作者: {{ post.author.username }} | 发布时间: {{ post.timestamp.strftime('%Y-%m-%d %H:%M') }}</p>
<hr>
<div class="well">{{ post.content }}</div>
<a href="{{ url_for('index') }}" class="btn btn-primary">返回首页</a>
{% endblock %}
3. 写文章模板templates/create_post.html¶
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}写文章 - 我的博客{% endblock %}
{% block content %}
<div class="col-md-6 col-md-offset-3">
<h2>写新文章</h2>
{{ wtf.quick_form(form, button_map={'submit': 'primary'}) }}
</div>
{% endblock %}
七、运行与测试¶
在终端执行以下命令启动博客系统:
python app.py
访问 http://127.0.0.1:5000 即可看到首页。若需发布文章,需先注册(本教程简化了注册功能,可自行扩展)或直接修改数据库添加用户。
八、总结与扩展¶
本教程实现了博客系统的核心功能:
- 首页展示文章列表
- 文章详情页
- 登录用户可发布文章
- 页面美化(Bootstrap)
可扩展方向:
1. 添加用户注册功能
2. 实现文章编辑/删除
3. 评论系统
4. 分类与标签功能
5. 文章搜索
通过这个项目,你将掌握Flask的基础使用、数据库操作、用户认证和模板渲染,为后续开发更复杂的Web应用打下基础。