当前位置:首页>python>Python之Flask开发框架(第三篇)

Python之Flask开发框架(第三篇)

  • 2026-10-11 19:29:24
Python之Flask开发框架(第三篇)

在前两篇教程中,我们从零开始搭建了 Flask 开发环境,掌握了路由、视图、模板、表单和数据库操作等核心技能。现在,你已经能够独立开发一个功能完整的 Web 应用。但一个成熟的应用不仅需要业务逻辑正确,还需要良好的可维护性、可扩展性以及生产环境的稳定性。

本篇将带你进入 Flask 的高级领域,内容包括:

  • 中间件
    :如何在请求处理的前后插入通用逻辑。
  • 扩展
    :利用 Flask 丰富的扩展生态快速集成认证、邮件、缓存等功能。
  • 部署
    :将应用安全高效地发布到生产环境。
  • 综合示例
    :整合所有知识,构建一个完整的博客系统。

1. Flask 中间件

在 Web 开发中,中间件指的是在请求到达视图函数之前或响应返回给客户端之后执行的一些代码。Flask 提供了多种装饰器来实现这种“钩子”功能,同时也支持标准的 WSGI 中间件。

1.1 请求/响应钩子

Flask 内置了以下常用钩子:

  • @app.before_request
    :在每个请求之前执行。
  • @app.after_request
    :在每个请求之后执行,必须接收并返回响应对象。
  • @app.teardown_request
    :在请求结束后执行,即使发生异常也会执行,用于清理资源。
  • @app.errorhandler
    :自定义错误处理,已在第二篇中介绍。

示例:记录请求耗时

import time
from flask import g

@app.before_request
defstart_timer():
    g.start = time.time()

@app.after_request
deflog_request(response):
    elapsed = time.time()- g.start
    app.logger.info(f'{request.method}{request.path} took {elapsed:.4f}s')
return response

示例:权限验证

@app.before_request
defcheck_auth():
if request.endpoint and request.endpoint notin['login','static']:
ifnot session.get('user_id'):
return redirect(url_for('auth.login'))

1.2 使用 WSGI 中间件

Flask 应用本身是一个 WSGI 应用,因此可以包裹在任意 WSGI 中间件中。例如,使用 werkzeug.middleware.profiler.ProfilerMiddleware 进行性能分析:

from werkzeug.middleware.profiler import ProfilerMiddleware

app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30])

常见的 WSGI 中间件包括:ProxyFix(处理反向代理头)、DispatcherMiddleware(多应用分发)等。


2. Flask 扩展

Flask 的“微型”哲学体现在核心只提供基础功能,而扩展则按需选择。以下是一些最常用、最成熟的扩展。

2.1 用户认证:Flask-Login

Flask-Login 管理用户会话,提供 login_user、logout_user、@login_required 等便捷功能。

安装:

pip install flask-login

初始化:

from flask_login import LoginManager

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view ='auth.login'# 未认证时重定向

用户模型:

from flask_login import UserMixin

classUser(UserMixin, db.Model):
id= db.Column(db.Integer, primary_key=True)
# ... 其他字段

加载用户回调:

@login_manager.user_loader
defload_user(user_id):
return User.query.get(int(user_id))

在视图中使用:

from flask_login import login_user, logout_user, login_required, current_user

@app.route('/login', methods=['POST'])
deflogin():
    user = User.query.filter_by(email=form.email.data).first()
if user and check_password_hash(user.password_hash, form.password.data):
        login_user(user)
return redirect(url_for('index'))
# ...

@app.route('/logout')
@login_required
deflogout():
    logout_user()
return redirect(url_for('index'))

在模板中,可以通过 current_user 访问当前用户信息。

2.2 邮件发送:Flask-Mail

安装:

pip install flask-mail

配置:

app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT']=587
app.config['MAIL_USE_TLS']=True
app.config['MAIL_USERNAME']='your-email@gmail.com'
app.config['MAIL_PASSWORD']='your-password'

发送邮件:

from flask_mail import Mail, Message

mail = Mail(app)

msg = Message('Hello', sender='noreply@example.com', recipients=['user@example.com'])
msg.body ='This is a test email.'
mail.send(msg)

2.3 缓存:Flask-Caching

安装:

pip install flask-caching

配置:

app.config['CACHE_TYPE']='SimpleCache'# 开发环境使用内存缓存
# 生产环境推荐 Redis: 'RedisCache'

使用:

from flask_caching import Cache

cache = Cache(app)

@cache.cached(timeout=300)
defget_expensive_data():
# 耗时操作
return result

在视图中也可以缓存整个响应:

@app.route('/')
@cache.cached(timeout=60)
defindex():
return render_template('index.html')

2.4 后台任务:Flask-RQ2(基于 Redis 队列)

安装:

pip install flask-rq2

初始化:

from flask_rq2 import RQ

rq = RQ(app)

定义任务:

@rq.job
defsend_welcome_email(user_id):
# 发送邮件的耗时逻辑
pass

调用任务:

send_welcome_email.delay(user.id)

2.5 其他常用扩展

  • Flask-Migrate
    :数据库迁移(已介绍)
  • Flask-Script
    :命令行扩展(已弃用,推荐使用 flask 命令)
  • Flask-RESTful / Flask-RESTx
    :快速构建 RESTful API
  • Flask-SocketIO
    :WebSocket 支持
  • Flask-CORS
    :处理跨域资源共享

3. 项目部署

将 Flask 应用部署到生产环境时,需要考虑性能、安全、可靠性。以下介绍几种主流方式。

3.1 传统部署:Gunicorn + Nginx

3.1.1 准备工作

  • 服务器:Linux(如 Ubuntu 20.04)
  • Python 虚拟环境
  • 项目代码

3.1.2 安装 Gunicorn

pip install gunicorn

3.1.3 使用 Gunicorn 启动应用

假设入口文件是 run.py,其中包含 app 对象:

gunicorn -w4-b127.0.0.1:8000 run:app
  • -w 4
    :4 个工作进程
  • -b
    :绑定地址和端口

3.1.4 配置 Nginx 作为反向代理

安装 Nginx:

sudoaptinstall nginx

创建站点配置 /etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /static {
        alias /path/to/your/project/app/static;
        expires 30d;
    }
}

启用配置并重启:

sudoln-s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx

3.1.5 使用 Supervisor 守护进程

安装 Supervisor:

sudoaptinstall supervisor

创建配置文件 /etc/supervisor/conf.d/myapp.conf:

[program:myapp]
command=/path/to/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 run:app
directory=/path/to/project
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/myapp.log
stderr_logfile=/var/log/myapp.err

启动并管理:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start myapp

3.2 容器化部署:Docker

使用 Docker 可以简化环境一致性。创建 Dockerfile:

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["gunicorn", "-b", "0.0.0.0:5000", "run:app"]

构建镜像并运行:

docker build -t myapp .
docker run -d-p5000:5000 --name myapp myapp

配合 Docker Compose 可以整合数据库等服务。

3.3 云平台部署

3.3.1 Heroku

  • 需要 Procfile:web: gunicorn run:app
  • 使用 heroku local 测试
  • 部署命令:git push heroku main

3.3.2 PythonAnywhere

  • 适合小型应用,提供免费层级
  • 通过 Web 界面配置 WSGI 文件

3.4 生产环境注意事项

  • 关闭调试模式
    :app.run(debug=False) 或通过环境变量 FLASK_ENV=production。
  • 使用环境变量管理敏感信息
    :例如数据库密码、密钥等,不要硬编码。
    import os
    app.config['SECRET_KEY']= os.environ.get('SECRET_KEY')
  • 静态文件服务
    :开发时由 Flask 提供,生产环境交给 Nginx 或 CDN。
  • 数据库连接池
    :SQLAlchemy 默认使用连接池,适当配置 SQLALCHEMY_POOL_SIZE。
  • 日志记录
    :配置合适的日志级别和输出位置。
  • 使用 HTTPS
    :配置 SSL 证书,可通过 Let’s Encrypt 免费获取。

4. 综合示例:简易博客系统

下面我们整合前两篇以及本篇所学,构建一个简易博客系统。功能包括:

  • 用户注册/登录(Flask-Login)
  • 发布/编辑/删除文章(数据库操作)
  • 文章列表与详情页(模板渲染)
  • 使用蓝图模块化
  • 使用 Flask-Mail 发送欢迎邮件
  • 使用 Flask-Caching 缓存首页

4.1 项目结构

blog/
├── app/
│   ├── __init__.py          # 应用工厂
│   ├── models.py            # 数据库模型
│   ├── forms.py             # 表单类
│   ├── auth/
│   │   ├── __init__.py
│   │   └── routes.py        # 认证相关路由
│   ├── main/
│   │   ├── __init__.py
│   │   └── routes.py        # 主要业务路由
│   ├── templates/           # 模板文件
│   └── static/              # 静态文件
├── config.py                # 配置类
├── run.py                   # 启动入口
├── requirements.txt
└── .env                     # 环境变量(不提交到版本库)

4.2 关键代码片段

config.py

import os
from dotenv import load_dotenv

load_dotenv()

classConfig:
    SECRET_KEY = os.environ.get('SECRET_KEY')or'dev-key'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')or'sqlite:///blog.db'
    SQLALCHEMY_TRACK_MODIFICATIONS =False
    MAIL_SERVER = os.environ.get('MAIL_SERVER')
    MAIL_PORT =int(os.environ.get('MAIL_PORT')or25)
    MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS','true').lower()in['true','on','1']
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')

app/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_mail import Mail
from flask_caching import Cache

db = SQLAlchemy()
migrate = Migrate()
login_manager = LoginManager()
mail = Mail()
cache = Cache()

defcreate_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)

    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)
    mail.init_app(app)
    cache.init_app(app)

    login_manager.login_view ='auth.login'
    login_manager.login_message ='请先登录'

from app.auth import auth_bp
from app.main import main_bp
    app.register_blueprint(auth_bp)
    app.register_blueprint(main_bp)

return app

app/models.py

from app import db
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime

classUser(UserMixin, db.Model):
id= db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), 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='dynamic')

defset_password(self, password):
        self.password_hash = generate_password_hash(password)

defcheck_password(self, password):
return check_password_hash(self.password_hash, password)

classPost(db.Model):
id= db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    body = 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'))

app/forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, TextAreaField
from wtforms.validators import DataRequired, Email, Length, EqualTo

classRegistrationForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(min=2,max=64)])
    email = StringField('邮箱', validators=[DataRequired(), Email()])
    password = PasswordField('密码', validators=[DataRequired(), Length(min=6)])
    confirm = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('注册')

classLoginForm(FlaskForm):
    email = StringField('邮箱', validators=[DataRequired(), Email()])
    password = PasswordField('密码', validators=[DataRequired()])
    submit = SubmitField('登录')

classPostForm(FlaskForm):
    title = StringField('标题', validators=[DataRequired()])
    body = TextAreaField('内容', validators=[DataRequired()])
    submit = SubmitField('发布')

app/auth/routes.py

from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_user, logout_user, current_user
from app import db, mail
from app.forms import RegistrationForm, LoginForm
from app.models import User
from flask_mail import Message

auth_bp = Blueprint('auth', __name__, url_prefix='/auth')

@auth_bp.route('/register', methods=['GET','POST'])
defregister():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
    form = RegistrationForm()
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()
# 发送欢迎邮件
        msg = Message('欢迎注册博客', recipients=[user.email])
        msg.body =f'你好 {user.username},感谢注册!'
        mail.send(msg)
        flash('注册成功,请登录','success')
return redirect(url_for('auth.login'))
return render_template('auth/register.html', form=form)

@auth_bp.route('/login', methods=['GET','POST'])
deflogin():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
    form = LoginForm()
if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
if user and user.check_password(form.password.data):
            login_user(user)
            next_page = request.args.get('next')
return redirect(next_page)if next_page else redirect(url_for('main.index'))
else:
            flash('邮箱或密码错误','danger')
return render_template('auth/login.html', form=form)

@auth_bp.route('/logout')
deflogout():
    logout_user()
return redirect(url_for('main.index'))

app/main/routes.py

from flask import Blueprint, render_template, redirect, url_for, flash, abort
from flask_login import login_required, current_user
from app import db, cache
from app.forms import PostForm
from app.models import Post

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
@cache.cached(timeout=60)
defindex():
    page = request.args.get('page',1,type=int)
    posts = Post.query.order_by(Post.created_at.desc()).paginate(page=page, per_page=10)
return render_template('main/index.html', posts=posts)

@main_bp.route('/post/<int:id>')
defpost_detail(id):
    post = Post.query.get_or_404(id)
return render_template('main/post_detail.html', post=post)

@main_bp.route('/create', methods=['GET','POST'])
@login_required
defcreate_post():
    form = PostForm()
if form.validate_on_submit():
        post = Post(title=form.title.data, body=form.body.data, author=current_user)
        db.session.add(post)
        db.session.commit()
        flash('文章发布成功','success')
return redirect(url_for('main.index'))
return render_template('main/create_post.html', form=form)

@main_bp.route('/edit/<int:id>', methods=['GET','POST'])
@login_required
defedit_post(id):
    post = Post.query.get_or_404(id)
if post.author != current_user:
        abort(403)
    form = PostForm()
if form.validate_on_submit():
        post.title = form.title.data
        post.body = form.body.data
        db.session.commit()
        flash('文章已更新','success')
return redirect(url_for('main.post_detail',id=post.id))
elif request.method =='GET':
        form.title.data = post.title
        form.body.data = post.body
return render_template('main/edit_post.html', form=form, post=post)

@main_bp.route('/delete/<int:id>', methods=['POST'])
@login_required
defdelete_post(id):
    post = Post.query.get_or_404(id)
if post.author != current_user:
        abort(403)
    db.session.delete(post)
    db.session.commit()
    flash('文章已删除','success')
return redirect(url_for('main.index'))

模板文件(略)

4.3 运行与测试

  1. 安装依赖:pip install -r requirements.txt
  2. 初始化数据库:flask db init && flask db migrate && flask db upgrade
  3. 设置环境变量(例如在 .env 中):
    FLASK_APP=run.py
    SECRET_KEY=your-secret-key
  4. 启动开发服务器:flask run
  5. 访问 http://127.0.0.1:5000 体验功能。

5. 总结与后续学习建议

经过三篇教程的学习,你已经从零开始构建了一个完整的 Flask 应用,并掌握了以下核心技能:

  • 基础入门:安装、路由、视图、模板、表单、数据库。
  • 进阶实战:中间件、常用扩展、项目组织。
  • 高级专题:中间件深入、扩展应用、生产部署。

Flask 的生态系统非常庞大,你可以继续探索以下方向:

  • REST API 开发
    :使用 Flask-RESTx 或 Marshmallow 构建规范化的 API。
  • 异步任务
    :使用 Celery 处理耗时任务。
  • 实时通信
    :WebSocket 与 Flask-SocketIO。
  • 性能优化
    :数据库索引、缓存策略、异步编程。
  • 安全加固
    :点击劫持保护、内容安全策略(CSP)、SQL 注入防护。

记住,实践是最好的老师。尝试自己动手扩展这个博客系统,比如添加评论功能、标签分类、用户头像上传等,在解决问题的过程中你会获得更深刻的理解。


资源推荐:

  • Flask 官方文档:https://flask.palletsprojects.com/
  • Flask Mega-Tutorial:https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
  • 优秀 Flask 扩展列表:https://github.com/rouge8/awesome-flask

欢迎关注公众号,感谢对文章的点赞分享喜欢,冉成未来会持续更新前后端开发技术、人工智能技术、IT相关的文章及学习经验、知识分享,未来虽然充满着不确定性,但我们可以不断提升自己,不断为未来做准备,让未来更好的自己成就更美好的未来。

Python之Flask开发框架(第二篇

Python之Flask开发框架(第一篇)

Python之FastAPI 开发知识(第五篇)

Python之FastAPI 开发知识(第四篇)

FastAPI 开发知识(第三篇)

FastAPI 开发知识(第二篇)

FastAPI 开发知识(第一篇)

Django 基础入门教程(第五篇)

Django 基础入门教程(第四篇)

Django 基础入门教程(第三篇)

 Django 基础入门教程(第二篇)

Django 基础入门教程(第一篇)

Python基础系列 | Python之PyQt5基础知识(五)

Python基础系列 | Python之PyQt5基础知识(四)

Python基础系列 | Python之PyQt5基础知识(三)

Python基础系列 | Python之PyQt5基础知识(二)

Python基础系列 | Python之PyQt5基础知识(一)

Python基础系列 | Scrapy框架详细解析

Python基础 | Python之Selenium测试工具集

Python基础系列 | Python爬虫技术(二)

Python基础系列 | Python爬虫技术(一)

Python基础系列 | Python设置pip镜像源

Python基础系列|Python基础知识(六)

Python基础系列|Python基础知识(五)

Python基础系列|Python基础知识(四)

Python基础系列|Python基础知识(三)

Python基础系列|Python基础知识(二)

Python基础系列|Python基础知识(一)

python中列表的处理

Python 基础语法入门:从零开始学习 Python

Windows环境下部署 Python 项目

干货|AI人工智能简介及python环境搭建

最新文章

随机文章