跳到主要内容

Blueprints

Blueprints 是 Flask 中组织大型应用的模块化方式,类似于 Django 的 app。

为什么使用 Blueprints

  • 模块化: 将应用拆分为逻辑组件
  • 可重用: 蓝图可以在多个应用间复用
  • 组织性: 更好的代码结构和维护性
  • URL 前缀: 为路由组设置统一前缀

基本结构

myapp/
├── app/
│ ├── __init__.py
│ ├── extensions.py
│ ├── config.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── user.py
│ ├── blueprints/
│ │ ├── __init__.py
│ │ ├── auth.py
│ │ ├── main.py
│ │ └── api.py
│ ├── templates/
│ └── static/
├── migrations/
├── tests/
├── requirements.txt
└── run.py

创建蓝图

主应用工厂

# app/__init__.py
from flask import Flask
from .extensions import db, login_manager, migrate
from .config import Config

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

# 初始化扩展
db.init_app(app)
login_manager.init_app(app)
migrate.init_app(app, db)

# 注册蓝图
from .blueprints.main import bp as main_bp
app.register_blueprint(main_bp)

from .blueprints.auth import bp as auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')

from .blueprints.api import bp as api_bp
app.register_blueprint(api_bp, url_prefix='/api/v1')

return app

扩展配置

# app/extensions.py
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate

db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()

主蓝图

# app/blueprints/main.py
from flask import Blueprint, render_template
from flask_login import login_required

bp = Blueprint('main', __name__)

@bp.route('/')
def index():
return render_template('main/index.html')

@bp.route('/about')
def about():
return render_template('main/about.html')

@bp.route('/dashboard')
@login_required
def dashboard():
return render_template('main/dashboard.html')

认证蓝图

# app/blueprints/auth.py
from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required
from app.extensions import db
from app.models.user import User
from app.forms.auth import LoginForm, RegistrationForm

bp = Blueprint('auth', __name__)

@bp.route('/register', methods=['GET', 'POST'])
def register():
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()
flash('注册成功!', 'success')
return redirect(url_for('auth.login'))
return render_template('auth/register.html', form=form)

@bp.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, remember=form.remember_me.data)
return redirect(url_for('main.index'))
flash('登录失败', 'danger')
return render_template('auth/login.html', form=form)

@bp.route('/logout')
@login_required
def logout():
logout_user()
flash('已退出登录', 'info')
return redirect(url_for('main.index'))

API 蓝图

# app/blueprints/api.py
from flask import Blueprint, jsonify, request
from app.models.user import User
from app.extensions import db

bp = Blueprint('api', __name__)

@bp.route('/users', methods=['GET'])
def get_users():
users = User.query.all()
return jsonify([user.to_dict() for user in users])

@bp.route('/users/<int:id>', methods=['GET'])
def get_user(id):
user = User.query.get_or_404(id)
return jsonify(user.to_dict())

@bp.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
user = User(username=data['username'], email=data['email'])
user.set_password(data['password'])
db.session.add(user)
db.session.commit()
return jsonify(user.to_dict()), 201

@bp.route('/users/<int:id>', methods=['PUT'])
def update_user(id):
user = User.query.get_or_404(id)
data = request.get_json()
user.username = data.get('username', user.username)
user.email = data.get('email', user.email)
db.session.commit()
return jsonify(user.to_dict())

@bp.route('/users/<int:id>', methods=['DELETE'])
def delete_user(id):
user = User.query.get_or_404(id)
db.session.delete(user)
db.session.commit()
return '', 204

蓝图配置

URL 前缀

# 所有路由自动添加前缀
app.register_blueprint(auth_bp, url_prefix='/auth')
# 访问 /auth/login, /auth/register

app.register_blueprint(api_bp, url_prefix='/api/v1')
# 访问 /api/v1/users

子域名

app.register_blueprint(api_bp, subdomain='api')
# 访问 api.example.com/users

静态文件

bp = Blueprint('auth', __name__,
static_folder='static',
static_url_path='/auth/static'
)

模板文件夹

bp = Blueprint('auth', __name__,
template_folder='templates/auth'
)

URL 生成

# 在蓝图中生成 URL
url_for('main.index') # -> /
url_for('auth.login') # -> /auth/login
url_for('api.get_users') # -> /api/v1/users

# 跨蓝图跳转
return redirect(url_for('main.index'))

蓝图错误处理

@bp.errorhandler(404)
def not_found(error):
return render_template('errors/404.html'), 404

@bp.errorhandler(500)
def internal_error(error):
db.session.rollback()
return render_template('errors/500.html'), 500

蓝图请求钩子

@bp.before_request
def before_request():
# 只对当前蓝图的路由生效
pass

@bp.after_request
def after_request(response):
return response

应用入口

# run.py
from app import create_app

app = create_app()

if __name__ == '__main__':
app.run(debug=True)

下一步

学习如何测试 Flask 应用。