Flask项目实战:个人博客系统开发教程

一、准备工作:安装必要工具和库

在开始前,确保你已经安装了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应用打下基础。

小夜