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應用打下基礎。

小夜