常用示例代码
1. 蓝图路由配置(模块化管理)
目录结构
project/
├── app.py # 主应用
└── users/ # 用户模块(蓝图)
├── __init__.py
├── views.py # 视图函数
└── templates/ # 蓝图模板
└── login.html
users/init.py(创建蓝图)
from flask import Blueprint
# 创建蓝图,指定模板目录和静态文件目录
users_bp = Blueprint(
'users',
__name__,
template_folder='templates',
static_folder='static',
static_url_path='/users/static'
)
# 导入视图(避免循环导入)
from . import views
users/views.py(蓝图路由)
from flask import render_template, url_for
from . import users_bp
@users_bp.route('/login', methods=['GET', 'POST'])
def login():
# 生成蓝图内路由的URL
register_url = url_for('users.register')
return render_template('login.html', register_url=register_url)
@users_bp.route('/register')
def register():
return "用户注册页面"
users/templates/login.html(蓝图模板)
{% extends "../base.html" %} # 继承项目根目录模板
{% block main %}
<h1>登录</h1>
<a href="{{ register_url }}">去注册</a>
{% endblock %}
app.py(主应用注册蓝图)
from flask import Flask
from users import users_bp
app = Flask(__name__)
app.config['DEBUG'] = True
# 注册蓝图,添加URL前缀
app.register_blueprint(users_bp, url_prefix='/users')
@app.route('/')
def index():
return "首页"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2. 模板继承示例
base.html(父模板)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{ title | default('默认标题') }}</title>
{% block css %}{% endblock %}
</head>
<body>
<header>公共头部</header>
{% block main %}
<p>默认内容</p>
{% endblock %}
<footer>公共底部</footer>
{% block js %}{% endblock %}
</body>
</html>
list.html(子模板)
{% extends "base.html" %}
{% block css %}
<style>body{color: red;}</style>
{% endblock %}
{% block main %}
{{ super() }} # 继承父模板内容
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endblock %}
3. 数据库模型与关联查询
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
# 一对多关系:老师 -> 课程
class Teacher(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
# 关联课程(反向引用为teacher)
courses = db.relationship('Course', backref='teacher', lazy='dynamic')
class Course(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
# 外键关联老师
teacher_id = db.Column(db.Integer, db.ForeignKey('teacher.id'))
# 多对多关系:学生 -> 课程
student_course = db.Table(
'student_course',
db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('course.id'))
)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
# 关联课程
courses = db.relationship(
'Course',
secondary=student_course,
backref=db.backref('students', lazy='dynamic'),
lazy='dynamic'
)
4. 请求钩子示例
@app.before_request
def before_request():
# 所有请求处理前执行(如权限验证)
print("请求到来了")
@app.after_request
def after_request(response):
# 响应返回前执行(如添加响应头)
response.headers['X-Framework'] = 'Flask'
return response
@app.teardown_request
def teardown_request(exc):
# 请求结束后执行(如异常记录)
if exc:
print(f"发生异常:{exc}")
标准 Flask 项目示例代码(前后端分离)
一、标准 Flask 项目目录结构(生产级)
project/ ├── app/ # 应用核心目录 │ ├── __init__.py # 应用工厂函数 │ ├── config/ # 配置文件 │ │ ├── __init__.py │ │ ├── base.py # 基础配置 │ │ ├── development.py # 开发环境 │ │ └── production.py # 生产环境 │ ├── models/ # 数据库模型(单独文件夹) │ │ ├── __init__.py │ │ ├── user.py # 用户模型 │ │ └── article.py # 文章模型 │ ├── api/ # API蓝图(按模块拆分) │ │ ├── __init__.py │ │ ├── v1/ # 版本1 │ │ │ ├── __init__.py │ │ │ ├── users.py # 用户相关接口 │ │ │ └── articles.py # 文章相关接口 │ ├── services/ # 业务逻辑层(可选) │ │ ├── __init__.py │ │ └── user_service.py # 用户业务处理 │ ├── schemas/ # 数据校验/序列化(可选,用marshmallow) │ │ ├── __init__.py │ │ └── user_schema.py │ ├── utils/ # 工具函数 │ │ ├── __init__.py │ │ ├── response.py # 响应格式化工具 │ │ └── validator.py # 通用校验 │ └── extensions.py # 扩展实例化(db、migrate等) ├── migrations/ # 数据库迁移文件(Flask-Migrate生成) ├── tests/ # 单元测试 ├── .env # 环境变量(不提交到git) ├── .gitignore ├── requirements.txt # 依赖列表 └── manage.py # 项目入口(启动、迁移等命令)
二、核心文件实现(含数据库模型 + 请求响应处理)
1. 数据库模型(单独管理)
app/extensions.py(扩展初始化,避免循环导入)
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy()
migrate = Migrate()
app/models/user.py(用户模型)
from datetime import datetime
from app.extensions import db
class User(db.Model):
__tablename__ = 'users' # 数据库表名
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), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关系:一个用户有多篇文章(一对多)
articles = db.relationship('Article', backref='author', lazy='dynamic')
def to_dict(self):
"""将模型转为字典(用于响应)"""
return {
'id': self.id,
'username': self.username,
'email': self.email,
'created_at': self.created_at.isoformat()
}
app/models/article.py(文章模型)
from datetime import datetime
from app.extensions import db
class Article(db.Model):
__tablename__ = 'articles'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128), nullable=False)
content = db.Column(db.Text, nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('users.id')) # 外键关联用户
created_at = db.Column(db.DateTime, default=datetime.utcnow)
2. 请求与响应处理(核心功能)
app/utils/response.py(统一响应格式化工具)
from flask import jsonify
def success(data=None, message="操作成功"):
"""成功响应"""
return jsonify({
'code': 200,
'message': message,
'data': data
})
def fail(message="操作失败", code=400):
"""失败响应"""
return jsonify({
'code': code,
'message': message,
'data': None
}), code # 第二个参数是HTTP状态码
app/api/v1/users.py(用户接口,含请求处理)
from flask import Blueprint, request, current_app
from app.extensions import db
from app.models.user import User
from app.utils.response import success, fail
from werkzeug.security import generate_password_hash # 密码加密
# 创建用户模块蓝图
users_bp = Blueprint('users', __name__)
@users_bp.route('', methods=['GET'])
def get_users():
"""获取用户列表(处理查询参数)"""
# 处理请求参数:/api/v1/users?page=1&size=10
page = request.args.get('page', 1, type=int)
size = request.args.get('size', 10, type=int)
# 分页查询
pagination = User.query.paginate(page=page, per_page=size)
users = pagination.items
# 构建响应
return success({
'total': pagination.total,
'page': page,
'size': size,
'items': [user.to_dict() for user in users]
})
@users_bp.route('', methods=['POST'])
def create_user():
"""创建用户(处理JSON/表单请求)"""
# 处理JSON请求体
data = request.get_json() # 若前端传JSON
# 若前端传表单:data = request.form.to_dict()
# 校验必填字段
if not all(k in data for k in ('username', 'email', 'password')):
return fail("缺少必填字段", 400)
# 检查用户是否已存在
if User.query.filter_by(username=data['username']).first():
return fail("用户名已存在", 409)
# 创建用户
try:
user = User(
username=data['username'],
email=data['email'],
password_hash=generate_password_hash(data['password']) # 加密存储
)
db.session.add(user)
db.session.commit()
return success(user.to_dict(), "用户创建成功"), 201 # 201表示创建成功
except Exception as e:
db.session.rollback()
current_app.logger.error(f"创建用户失败: {str(e)}") # 日志记录
return fail("服务器错误", 500)
@users_bp.route('/<int:user_id>', methods=['GET'])
def get_user(user_id):
"""获取单个用户(路径参数)"""
user = User.query.get_or_404(user_id) # 不存在返回404
return success(user.to_dict())
3. 蓝图注册与应用初始化
app/api/v1/init.py(注册 v1 版本蓝图)
from flask import Blueprint
from .users import users_bp
from .articles import articles_bp # 假设存在文章接口
# 创建v1版本总蓝图
api_v1_bp = Blueprint('api_v1', __name__, url_prefix='/api/v1')
# 注册子蓝图
api_v1_bp.register_blueprint(users_bp, url_prefix='/users')
api_v1_bp.register_blueprint(articles_bp, url_prefix='/articles')
app/init.py(应用工厂函数)
from flask import Flask
from app.config import config
from app.extensions import db, migrate
from app.api.v1 import api_v1_bp
def create_app(config_name='development'):
app = Flask(__name__)
app.config.from_object(config[config_name]) # 加载配置
# 初始化扩展
db.init_app(app)
migrate.init_app(app, db)
# 注册蓝图
app.register_blueprint(api_v1_bp)
return app
4. 项目入口(manage.py)
import os
from flask_migrate import MigrateCommand
from flask_script import Manager
from app import create_app
from app.extensions import db
app = create_app(os.getenv('FLASK_ENV', 'development'))
manager = Manager(app)
# 添加数据库迁移命令
manager.add_command('db', MigrateCommand)
# 自定义命令:创建管理员用户
@manager.command
def create_superuser():
from app.models.user import User
from werkzeug.security import generate_password_hash
username = input("请输入管理员用户名: ")
email = input("请输入管理员邮箱: ")
password = input("请输入管理员密码: ")
user = User(
username=username,
email=email,
password_hash=generate_password_hash(password)
)
db.session.add(user)
db.session.commit()
print("超级管理员创建成功!")
if __name__ == '__main__':
manager.run()
示例代码(前后端不分离)
一、含模板文件的目录结构(前后端不分离)
在原有结构基础上,增加模板(templates
)和静态文件(static
)目录:
project/
├── app/
│ ├── models/ # 数据库模型
│ ├── api/ # API接口(前后端分离用)
│ ├── web/ # 新增:Web页面模块(含蓝图和模板)
│ │ ├── users/ # 用户相关页面模块
│ │ │ ├── __init__.py # 蓝图定义
│ │ │ ├── views.py # 视图函数(渲染HTML)
│ │ │ ├── templates/ # 蓝图专属模板(优先重名)
│ │ │ │ └── users/ # 建议再嵌套一层同名文件夹,避免与其他蓝图冲突
│ │ │ │ ├── login.html
│ │ │ │ └── profile.html
│ │ │ └── static/ # 蓝图专属静态文件(CSS/JS/图片)
│ │ │ └── css/
│ │ │ └── user.css
│ ├── templates/ # 全局模板(公共组件,如base.html)
│ │ └── base.html
│ └── static/ # 全局静态文件(如全局CSS/JS)
│ └── js/
│ └── common.js
二、蓝图指定模板 / 静态文件夹的正确配置
app/web/users/init.py(创建蓝图时指定路径):
from flask import Blueprint
# 关键:指定蓝图专属的模板和静态文件目录
users_bp = Blueprint(
'users', # 蓝图名(唯一标识)
__name__,
url_prefix='/users', # URL前缀
template_folder='templates', # 模板文件夹(相对当前文件的路径)
static_folder='static', # 静态文件文件夹
static_url_path='/users/static' # 静态文件访问URL(避免与全局静态文件冲突)
)
# 导入视图(放在蓝图定义后,避免循环导入)
from . import views
三、视图函数渲染模板示例
app/web/users/views.py:
from flask import render_template, redirect, url_for, request, flash
from . import users_bp
from app.models.user import User
from app.extensions import db
@users_bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
# 处理表单提交(获取表单数据)
username = request.form.get('username')
password = request.form.get('password')
# 简单验证(实际项目需加密码校验)
user = User.query.filter_by(username=username).first()
if user:
flash('登录成功', 'success') # 消息提示
return redirect(url_for('users.profile', user_id=user.id))
else:
flash('用户名或密码错误', 'danger')
# 渲染蓝图专属模板(会自动查找 users/templates/users/login.html)
return render_template('users/login.html')
@users_bp.route('/profile/<int:user_id>')
def profile(user_id):
user = User.query.get_or_404(user_id)
# 继承全局模板 base.html
return render_template('users/profile.html', user=user)
四、模板文件内容示例
1、全局模板(app/templates/base.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Flask项目{% endblock %}</title>
<!-- 引入全局静态文件 -->
<script src="{{ url_for('static', filename='js/common.js') }}"></script>
{% block css %}{% endblock %} <!-- 预留CSS块 -->
</head>
<body>
<header>导航栏</header>
<!-- 消息提示(全局通用) -->
{% 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 %}
<main>{% block content %}{% endblock %}</main> <!-- 内容块 -->
<footer>页脚</footer>
{% block js %}{% endblock %} <!-- 预留JS块 -->
</body>
</html>
2、蓝图专属模板(app/web/users/templates/users/login.html):
{% extends "base.html" %} <!-- 继承全局模板 -->
{% block title %}用户登录{% endblock %}
{% block css %}
<!-- 引入蓝图专属CSS -->
<link rel="stylesheet" href="{{ url_for('users.static', filename='css/user.css') }}">
{% endblock %}
{% block content %}
<h1>用户登录</h1>
<form method="POST">
<div>
<label>用户名:</label>
<input type="text" name="username" required>
</div>
<div>
<label>密码:</label>
<input type="password" name="password" required>
</div>
<button type="submit">登录</button>
</form>
{% endblock %}