项目进度: 0%
Web开发

个人博客系统开发

项目概述

本项目将带领大家使用Flask框架开发一个功能完整的个人博客系统。通过这个项目,你将学习到Web开发的核心概念和实践技能。

项目特点:

  • 完整的用户认证系统
  • 文章的CRUD操作
  • 评论和回复功能
  • Markdown编辑器支持
  • 响应式页面设计

技术栈说明

后端技术

  • Flask - Web框架
  • SQLite - 数据库
  • SQLAlchemy - ORM框架
  • Flask-Login - 用户认证

前端技术

  • Bootstrap - UI框架
  • SimpleMDE - Markdown编辑器
  • jQuery - JavaScript库

项目结构

blog/
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── routes.py
│   └── templates/
├── config.py
├── requirements.txt
└── run.py

数据库设计

我们使用SQLAlchemy作为ORM框架,设计以下数据模型:

# models.py
from app import db
from datetime import datetime

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(128))
    posts = db.relationship('Post', backref='author', lazy=True)

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)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    comments = db.relationship('Comment', backref='post', lazy=True)

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)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)

用户认证

使用Flask-Login实现用户认证系统:

# routes.py
from flask import render_template, flash, redirect, url_for
from flask_login import login_user, logout_user, login_required
from app import app, db
from app.models import User
from app.forms import LoginForm, RegisterForm

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, email=form.email.data)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('注册成功!')
        return redirect(url_for('login'))
    return render_template('auth/register.html', form=form)

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = 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'))
        flash('用户名或密码错误')
    return render_template('auth/login.html', form=form)

文章管理

实现文章的CRUD操作:

# routes.py
@app.route('/post/new', methods=['GET', 'POST'])
@login_required
def new_post():
    form = PostForm()
    if form.validate_on_submit():
        post = Post(title=form.title.data,
                   content=form.content.data,
                   author=current_user)
        db.session.add(post)
        db.session.commit()
        flash('文章发布成功!')
        return redirect(url_for('post', post_id=post.id))
    return render_template('post/editor.html', form=form)

@app.route('/post/')
def post(post_id):
    post = Post.query.get_or_404(post_id)
    return render_template('post/detail.html', post=post)

@app.route('/post//edit', methods=['GET', 'POST'])
@login_required
def edit_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author != current_user:
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data
        db.session.commit()
        flash('文章更新成功!')
        return redirect(url_for('post', post_id=post.id))
    form.title.data = post.title
    form.content.data = post.content
    return render_template('post/editor.html', form=form, edit=True)

@app.route('/post//delete', methods=['POST'])
@login_required
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author != current_user:
        abort(403)
    db.session.delete(post)
    db.session.commit()
    flash('文章已删除')
    return redirect(url_for('index'))

安全提示:

  • 验证用户权限
  • 防止CSRF攻击
  • 过滤用户输入
  • 限制请求频率

评论系统

实现评论和回复功能:

# routes.py
@app.route('/post//comment', methods=['POST'])
@login_required
def add_comment(post_id):
    post = Post.query.get_or_404(post_id)
    form = CommentForm()
    if form.validate_on_submit():
        comment = Comment(content=form.content.data,
                         post=post,
                         author=current_user)
        db.session.add(comment)
        db.session.commit()
        flash('评论发布成功!')
    return redirect(url_for('post', post_id=post_id))

@app.route('/comment//reply', methods=['POST'])
@login_required
def reply_comment(comment_id):
    parent = Comment.query.get_or_404(comment_id)
    form = CommentForm()
    if form.validate_on_submit():
        reply = Comment(content=form.content.data,
                        post=parent.post,
                        author=current_user,
                        parent_id=parent.id)
        db.session.add(reply)
        db.session.commit()
        flash('回复发布成功!')
    return redirect(url_for('post', post_id=parent.post_id))
# templates/post/detail.html
{% for comment in post.comments %}
    
{{ comment.content }}
{{ comment.author.username }} {{ comment.created_at.strftime('%Y-%m-%d %H:%M') }}
{% if current_user.is_authenticated %} {% endif %}
{% endfor %}

项目部署

使用Gunicorn和Nginx部署项目:

# gunicorn配置
gunicorn -w 4 -b 127.0.0.1:8000 run:app

# nginx配置
server {
    listen 80;
    server_name your_domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}