Flask 入门详解:从零开始构建 Web 应用

发布于:2025-08-19 ⋅ 阅读:(13) ⋅ 点赞:(0)

Flask 是一个使用 Python 编写的轻量级 Web 应用框架。它"微"(micro)的含义是 Flask 保持核心简单但可扩展,让你可以根据需要选择合适的工具和库。


一、为什么选择 Flask?

优势

说明

轻量级

核心简单,学习曲线平缓

灵活性

可自由选择数据库、模板引擎等组件

Pythonic

代码简洁,符合 Python 哲学

强大扩展

拥有丰富的第三方扩展

适合学习

理解 Web 开发基础概念的理想选择

💡 适用场景:小型网站、API 服务、学习 Web 开发、原型开发


二、环境准备

1. 安装 Python

确保已安装 Python 3.6+:

python --version
# 或
python3 --version

2. 创建虚拟环境(推荐)

# 创建虚拟环境
python -m venv flask-env

# 激活虚拟环境
# Windows:
flask-env\Scripts\activate
# macOS/Linux:
source flask-env/bin/activate

3. 安装 Flask

pip install Flask

验证安装:

python -c "import flask; print(flask.__version__)"

三、第一个 Flask 应用

1. 基础应用结构

创建文件 app.py

from flask import Flask

# 创建 Flask 应用实例
app = Flask(__name__)

# 定义路由和视图函数
@app.route('/')
def hello():
    return 'Hello, Flask!'

# 运行应用
if __name__ == '__main__':
    app.run(debug=True)

2. 运行应用

python app.py

访问 http://127.0.0.1:5000,你应该能看到 "Hello, Flask!"

🔥 关键概念

  • Flask(__name__):创建应用实例
  • @app.route():装饰器,定义 URL 路由
  • debug=True:开启调试模式,代码修改后自动重启

四、路由与视图

1. 基本路由

@app.route('/')
def index():
    return '<h1>首页</h1>'

@app.route('/about')
def about():
    return '<h1>关于</h1>'

2. 变量规则

@app.route('/user/<username>')
def show_user(username):
    return f'用户: {username}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'文章ID: {post_id}'

支持的类型转换器

  • string:(默认)接受任何不包含斜杠的文本
  • int:整数
  • float:浮点数
  • path:类似 string,但接受斜杠
  • uuid:UUID 字符串

3. HTTP 方法

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return '处理登录表单'
    else:
        return '''
        <form method="post">
            <input type="text" name="username" placeholder="用户名">
            <input type="password" name="password" placeholder="密码">
            <input type="submit" value="登录">
        </form>
        '''

4. URL 构建

from flask import url_for

@app.route('/admin')
def admin():
    return '管理员页面'

@app.route('/link')
def link():
    # 生成 URL
    admin_url = url_for('admin')
    return f'<a href="{admin_url}">进入管理后台</a>'

五、模板渲染(Jinja2)

Flask 使用 Jinja2 模板引擎。

1. 创建模板目录

your-project/
├── app.py
└── templates/
    └── index.html

2. 创建模板文件 templates/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>{{ title }}</title>
  </head>
  <body>
    <h1>{{ title }}</h1>
    <p>欢迎,{{ name }}!</p>

    <!-- 条件语句 -->
    {% if age >= 18 %}
    <p>您已成年</p>
    {% else %}
    <p>您未成年</p>
    {% endif %}

    <!-- 循环 -->
    <ul>
      {% for item in items %}
      <li>{{ item }}</li>
      {% endfor %}
    </ul>
  </body>
</html>

3. 渲染模板

from flask import render_template

@app.route('/hello/<name>')
def hello_template(name):
    return render_template(
        'index.html',
        title='欢迎页面',
        name=name,
        age=25,
        items=['苹果', '香蕉', '橙子']
    )

4. 模板继承

创建基础模板 templates/base.html

<!DOCTYPE html>
<html>
  <head>
    {% block title %}<title>默认标题</title>{% endblock %}
  </head>
  <body>
    <nav>
      <a href="{{ url_for('index') }}">首页</a>
      <a href="{{ url_for('about') }}">关于</a>
    </nav>

    <main>
      {% block content %}{% endblock %}
    </main>
  </body>
</html>

创建子模板 templates/about.html

{% extends "base.html" %}

{% block title %}<title>关于我们</title>{% endblock %}

{% block content %}
<h1>关于我们</h1>
<p>这里是关于页面的内容...</p>
{% endblock %}

六、请求与响应处理

1. 处理请求数据

from flask import request, jsonify

@app.route('/api/data', methods=['POST'])
def handle_data():
    # 获取 JSON 数据
    data = request.get_json()

    # 获取表单数据
    username = request.form.get('username')
    password = request.form.get('password')

    # 获取查询参数
    page = request.args.get('page', 1, type=int)

    return jsonify({
        'received': data,
        'username': username,
        'page': page
    })

2. 返回不同类型的响应

from flask import jsonify, make_response, send_file

# JSON 响应
@app.route('/api/user')
def api_user():
    return jsonify({'name': '张三', 'age': 30})

# 自定义响应
@app.route('/custom')
def custom_response():
    response = make_response('<h1>自定义响应</h1>', 201)
    response.headers['X-Custom-Header'] = 'Value'
    return response

# 文件响应
@app.route('/download')
def download_file():
    return send_file('path/to/file.pdf', as_attachment=True)

七、静态文件

Flask 自动提供 static 文件夹中的文件。

目录结构:

your-project/
├── app.py
├── static/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── images/
│       └── logo.png
└── templates/

在模板中使用:

<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">

八、表单处理

1. 简单表单处理

from flask import request, redirect, url_for, flash

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form['name']
        email = request.form['email']
        message = request.form['message']

        # 验证数据
        if not name or not email:
            flash('请填写必填字段!')
            return redirect(url_for('contact'))

        # 处理表单数据(如发送邮件、保存到数据库)
        save_message(name, email, message)

        flash('消息已发送!')
        return redirect(url_for('contact'))

    return '''
    <form method="post">
        <input type="text" name="name" placeholder="姓名" required><br>
        <input type="email" name="email" placeholder="邮箱" required><br>
        <textarea name="message" placeholder="消息"></textarea><br>
        <input type="submit" value="发送">
    </form>
    '''

2. 使用 Flask-WTF(推荐)

安装:

pip install Flask-WTF
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email

class ContactForm(FlaskForm):
    name = StringField('姓名', validators=[DataRequired()])
    email = StringField('邮箱', validators=[DataRequired(), Email()])
    message = TextAreaField('消息')
    submit = SubmitField('发送')

@app.route('/contact', methods=['GET', 'POST'])
def contact_wtf():
    form = ContactForm()
    if form.validate_on_submit():
        # 处理表单数据
        save_message(form.name.data, form.email.data, form.message.data)
        flash('消息已发送!')
        return redirect(url_for('contact_wtf'))

    return render_template('contact.html', form=form)

模板 templates/contact.html

<form method="post">
  {{ form.hidden_tag() }}
  <p>
    {{ form.name.label }}<br>
    {{ form.name(size=32) }}
    {% for error in form.name.errors %}
    <span style="color: red;">[{{ error }}]</span>
    {% endfor %}
  </p>
  <p>
    {{ form.email.label }}<br>
    {{ form.email(size=32) }}
    {% for error in form.email.errors %}
    <span style="color: red;">[{{ error }}]</span>
    {% endfor %}
  </p>
  <p>
    {{ form.message.label }}<br>
    {{ form.message(rows=4, cols=32) }}
  </p>
  <p>{{ form.submit() }}</p>
</form>

九、数据库集成(Flask-SQLAlchemy)

1. 安装

pip install Flask-SQLAlchemy

2. 配置和模型

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 配置数据库(这里使用 SQLite)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 定义模型
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)

    def __repr__(self):
        return f'<User {self.username}>'

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship('User', backref=db.backref('posts', lazy=True))

3. 数据库操作

@app.route('/users', methods=['GET', 'POST'])
def users():
    if request.method == 'POST':
        # 创建新用户
        username = request.form['username']
        email = request.form['email']
        user = User(username=username, email=email)
        db.session.add(user)
        db.session.commit()
        flash('用户创建成功!')

    # 查询所有用户
    users = User.query.all()
    return render_template('users.html', users=users)

@app.route('/users/<int:user_id>')
def user_detail(user_id):
    user = User.query.get_or_404(user_id)
    return render_template('user_detail.html', user=user)

4. 初始化数据库

# 在 Python 交互环境中
from app import db
db.create_all()  # 创建所有表

十、用户认证(Flask-Login)

1. 安装

pip install Flask-Login

2. 配置

from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# 用户模型需要继承 UserMixin
class User(UserMixin, db.Model):
    # ... 其他字段
    pass

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.query.filter_by(username=username).first()

        if user and check_password(password, user.password):  # 实际需要密码哈希
            login_user(user)
            return redirect(url_for('dashboard'))
        else:
            flash('用户名或密码错误')

    return render_template('login.html')

@app.route('/dashboard')
@login_required  # 装饰器确保用户已登录
def dashboard():
    return f'欢迎,{current_user.username}!'

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

十一、项目结构建议

对于稍大的项目,建议使用包结构:

my_flask_app/
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── routes.py
│   ├── forms.py
│   └── templates/
│       └── ...
├── migrations/          # 数据库迁移
├── static/
├── tests/
├── config.py
└── run.py

app/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

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

    db.init_app(app)

    from app.routes import main_bp
    app.register_blueprint(main_bp)

    return app

run.py

from app import create_app

app = create_app()

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

十二、常用扩展

扩展

用途

Flask-WTF

表单处理和验证

Flask-SQLAlchemy

数据库 ORM

Flask-Migrate

数据库迁移

Flask-Login

用户认证

Flask-Mail

邮件发送

Flask-RESTful

构建 REST API

Flask-CORS

处理跨域请求

Flask-Caching

缓存支持

安装扩展:

pip install Flask-WTF Flask-SQLAlchemy Flask-Migrate Flask-Login

十三、部署准备

1. 环境变量

创建 .env 文件:

FLASK_APP=app.py
FLASK_ENV=production
SECRET_KEY=your-secret-key-here
DATABASE_URL=sqlite:///prod.db

2. 生产服务器

不要使用 Flask 内置服务器进行生产部署。推荐使用:

Gunicorn

pip install gunicorn
gunicorn -w 4 app:app

uWSGI

pip install uwsgi
uwsgi --http :5000 --wsgi-file app.py --callable app

3. 与 Nginx 配合

Nginx 作为反向代理,处理静态文件和负载均衡。


十四、学习资源

  1. 官方文档Welcome to Flask — Flask Documentation (3.1.x)
  2. Flask 教程Tutorial — Flask Documentation (3.1.x)
  3. Real Python Flask 教程Flask Tutorials – Real Python
  4. 《Flask Web 开发》:Miguel Grinberg 著

十五、总结

Flask 特性

说明

轻量核心

只包含最基本的功能

灵活扩展

通过扩展添加所需功能

开发友好

调试模式、开发服务器

社区活跃

丰富的文档和第三方库

适合学习

理解 Web 开发基础

Flask 是学习 Python Web 开发的绝佳起点。它让你从基础开始,逐步构建复杂的应用,同时保持代码的清晰和可维护性。


网站公告

今日签到

点亮在社区的每一天
去签到