让我们从一个最简单的单文件Flask应用开始:
from flask import Flask
# 创建Flask应用实例
app = Flask(__name__)
# 定义路由和视图函数
@app.route('/')
def hello_world():
return 'Hello, World!'
# 添加另一个路由
@app.route('/hello/<name>')
def hello_name(name):
return f'Hello, {name}! Welcome to Flask!'
# 主程序入口
if __name__ == '__main__':
app.run(
debug=True, # 开启调试模式
host='127.0.0.1', # 本地主机
port=5000 # 端口号
)
# 确保在项目目录中
python app.py
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
为了更好的可维护性,我们采用标准项目结构:
myflaskproject/
│
├── app/ # 应用包
│ ├── __init__.py # 初始化文件,创建Flask应用
│ ├── routes.py # 路由定义
│ ├── models.py # 数据模型(后续章节讲解)
│ ├── forms.py # 表单定义(后续章节讲解)
│ ├── errors.py # 错误处理
│ │
│ ├── templates/ # 模板目录
│ │ ├── base.html # 基础模板
│ │ ├── index.html # 首页模板
│ │ ├── about.html # 关于页面
│ │ └── errors/ # 错误页面目录
│ │ ├── 404.html
│ │ └── 500.html
│ │
│ └── static/ # 静态文件目录
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── main.js
│ └── images/
│ └── logo.png
│
├── migrations/ # 数据库迁移文件(后续添加)
├── tests/ # 测试文件
│ ├── __init__.py
│ └── test_basic.py
│
├── config.py # 配置文件
├── requirements.txt # 依赖列表
├── .env # 环境变量(可选)
├── .gitignore # Git忽略文件
└── run.py # 启动脚本
from flask import Flask
from config import Config
def create_app(config_class=Config):
"""应用工厂函数"""
app = Flask(__name__)
app.config.from_object(config_class)
# 注册蓝图
from app.routes import main_bp
app.register_blueprint(main_bp)
# 注册错误处理器
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
return app
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
class Config:
"""基础配置类"""
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-123'
DEBUG = True
# 静态文件配置
STATIC_FOLDER = 'static'
TEMPLATES_FOLDER = 'templates'
from flask import Blueprint, render_template, request, jsonify
from datetime import datetime
# 创建蓝图
main_bp = Blueprint('main', __name__)
# 主页
@main_bp.route('/')
@main_bp.route('/index')
def index():
"""首页"""
return render_template('index.html',
title='Flask首页',
current_time=datetime.now())
# 关于页面
@main_bp.route('/about')
def about():
"""关于页面"""
return render_template('about.html',
title='关于我们',
year=datetime.now().year)
# 用户问候页面
@main_bp.route('/user/<username>')
def user_profile(username):
"""用户个人页面"""
return render_template('user.html',
username=username,
title=f'{username}的主页')
# API接口示例
@main_bp.route('/api/data')
def get_data():
"""返回JSON数据"""
data = {
'status': 'success',
'message': '数据获取成功',
'timestamp': datetime.now().isoformat(),
'data': {
'users': 100,
'active': 75
}
}
return jsonify(data)
# 表单提交示例
@main_bp.route('/submit', methods=['GET', 'POST'])
def submit():
"""处理表单提交"""
if request.method == 'POST':
name = request.form.get('name', '匿名')
return f'你好,{name}!感谢提交表单。'
# GET请求返回表单页面
return '''
<form method="post">
<label>姓名:</label>
<input type="text" name="name">
<button type="submit">提交</button>
</form>
'''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{{ title }} - Flask应用{% endblock %}</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
{% block head %}{% endblock %}
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="{{ url_for('main.index') }}">
<i class="fas fa-flask me-2"></i>Flask应用
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.index') }}">
<i class="fas fa-home me-1"></i>首页
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.about') }}">
<i class="fas fa-info-circle me-1"></i>关于
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.get_data') }}">
<i class="fas fa-database me-1"></i>API
</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- 主要内容 -->
<main class="container my-4">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info alert-dismissible fade show">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
<!-- 页脚 -->
<footer class="bg-light text-center py-3 mt-5">
<div class="container">
<p class="mb-0">
© {{ year if year else 2023 }} Flask应用 |
<a href="{{ url_for('main.about') }}" class="text-decoration-none">关于我们</a>
</p>
</div>
</footer>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- 自定义JS -->
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8 mx-auto text-center">
<h1 class="display-4 text-primary mb-4">
<i class="fas fa-flask"></i> 欢迎来到Flask世界!
</h1>
<p class="lead">
这是一个使用Flask构建的完整Web应用示例。当前时间:{{ current_time.strftime('%Y-%m-%d %H:%M:%S') }}
</p>
<div class="card shadow-sm my-4">
<div class="card-body">
<h5 class="card-title">快速开始</h5>
<p class="card-text">尝试以下功能:</p>
<div class="row mt-3">
<div class="col-md-4">
<a href="{{ url_for('main.about') }}" class="btn btn-outline-primary w-100 mb-2">
<i class="fas fa-info-circle"></i> 关于页面
</a>
</div>
<div class="col-md-4">
<a href="{{ url_for('main.user_profile', username='访客') }}" class="btn btn-outline-success w-100 mb-2">
<i class="fas fa-user"></i> 用户页面
</a>
</div>
<div class="col-md-4">
<a href="{{ url_for('main.get_data') }}" class="btn btn-outline-info w-100 mb-2">
<i class="fas fa-database"></i> API数据
</a>
</div>
</div>
</div>
</div>
<!-- 动态表单 -->
<div class="card shadow-sm my-4">
<div class="card-body">
<h5 class="card-title">互动表单</h5>
<form action="{{ url_for('main.submit') }}" method="post" class="mt-3">
<div class="input-group">
<input type="text" name="name" class="form-control" placeholder="请输入您的姓名" required>
<button type="submit" class="btn btn-primary">
<i class="fas fa-paper-plane"></i> 提交问候
</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
/* 自定义样式表 */
/* 全局样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f8f9fa;
}
/* 导航栏 */
.navbar-brand {
font-weight: bold;
}
/* 卡片样式 */
.card {
border: none;
transition: transform 0.3s;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.1) !important;
}
/* 按钮样式 */
.btn {
border-radius: 20px;
padding: 8px 20px;
}
.btn-outline-primary:hover {
background-color: #0d6efd;
color: white;
}
/* 页脚样式 */
footer {
border-top: 1px solid #dee2e6;
}
/* 响应式调整 */
@media (max-width: 768px) {
.display-4 {
font-size: 2rem;
}
.lead {
font-size: 1rem;
}
}
// 主JavaScript文件
document.addEventListener('DOMContentLoaded', function() {
console.log('Flask应用已加载');
// 示例:显示当前时间
function updateTime() {
const timeElement = document.getElementById('current-time');
if (timeElement) {
const now = new Date();
timeElement.textContent = now.toLocaleString();
}
}
// 每秒钟更新时间
setInterval(updateTime, 1000);
updateTime();
// 表单提交提示
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
const submitBtn = this.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.innerHTML = ' 处理中...';
submitBtn.disabled = true;
}
});
});
// 返回顶部按钮
const backToTop = document.createElement('button');
backToTop.innerHTML = '';
backToTop.className = 'btn btn-primary btn-floating';
backToTop.style.position = 'fixed';
backToTop.style.bottom = '20px';
backToTop.style.right = '20px';
backToTop.style.display = 'none';
backToTop.style.zIndex = '1000';
backToTop.addEventListener('click', function() {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
document.body.appendChild(backToTop);
window.addEventListener('scroll', function() {
if (window.pageYOffset > 300) {
backToTop.style.display = 'block';
} else {
backToTop.style.display = 'none';
}
});
});
from flask import Blueprint, render_template
bp = Blueprint('errors', __name__)
@bp.app_errorhandler(404)
def not_found_error(error):
"""404错误处理"""
return render_template('errors/404.html', title='页面未找到'), 404
@bp.app_errorhandler(500)
def internal_error(error):
"""500错误处理"""
return render_template('errors/500.html', title='服务器错误'), 500
@bp.app_errorhandler(403)
def forbidden_error(error):
"""403错误处理"""
return render_template('errors/403.html', title='禁止访问'), 403
{% extends "base.html" %}
{% block content %}
<div class="text-center py-5">
<h1 class="display-1 text-muted">404</h1>
<h2 class="mb-4">页面未找到</h2>
<p class="lead mb-4">
抱歉,您访问的页面不存在或已被移除。
</p>
<div class="mb-3">
<i class="fas fa-search fa-4x text-warning mb-4"></i>
</div>
<a href="{{ url_for('main.index') }}" class="btn btn-primary btn-lg">
<i class="fas fa-home me-2"></i>返回首页
</a>
</div>
{% endblock %}
#!/usr/bin/env python
"""应用启动脚本"""
import os
from app import create_app
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 创建应用实例
app = create_app()
if __name__ == '__main__':
# 获取环境变量中的配置,或使用默认值
host = os.environ.get('FLASK_HOST', '127.0.0.1')
port = int(os.environ.get('FLASK_PORT', 5000))
debug = os.environ.get('FLASK_DEBUG', 'True').lower() in ['true', '1']
print(f"""
========================================
Flask应用启动中...
访问地址: http://{host}:{port}
调试模式: {debug}
========================================
""")
app.run(host=host, port=port, debug=debug)
Flask==2.3.2
python-dotenv==1.0.0
# 开发环境依赖(可选)
blinker==1.6.2
click==8.1.3
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
Werkzeug==2.3.6
# 方式1:直接运行(推荐)
python run.py
# 方式2:使用Flask命令行
export FLASK_APP=run.py
export FLASK_ENV=development
flask run
# 方式3:使用gunicorn(生产环境)
pip install gunicorn
gunicorn -w 4 -b 127.0.0.1:8000 run:app
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/
# Flask
instance/
.webassets-cache
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# 环境变量
.env
.env.local
.env.*.local
完成以上步骤后,测试以下功能是否正常:
http://127.0.0.1:5000/ 显示首页http://127.0.0.1:5000/about 显示关于页面http://127.0.0.1:5000/user/张三 显示用户页面http://127.0.0.1:5000/api/data 返回JSON数据接下来可以学习: