一、认识 Flask

Flask 是一个用 Python 编写的 轻量级 Web 框架
它核心很小,但扩展性极强——既适合做简单的 API,也能通过插件构建大型项目。

为什么选 Flask?

  • 极简:几行代码就能跑起来
  • 灵活:不强求你使用特定数据库或目录结构
  • 易学:非常适合作为第一个 Web 框架
  • 生态丰富:有大量扩展(如 Flask-SQLAlchemy、Flask-Login)

二、环境准备

建议使用 虚拟环境 隔离依赖。

# 创建项目文件夹
mkdir flask-intro
cd flask-intro

# 创建虚拟环境(Windows 用 venv\Scripts\activate)
python3 -m venv venv
source venv/bin/activate

# 安装 Flask
pip install Flask

三、第一个 Flask 应用

新建 app.py

from flask import Flask

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

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

# 只有直接运行该脚本时才启动服务器
if __name__ == '__main__':
    app.run(debug=True)

启动:python app.py
浏览器访问 http://127.0.0.1:5000,即可看到 “你好,Flask!”。

debug=True 开启调试模式,代码修改后自动重启,出错时在浏览器中显示详细错误信息(生产环境务必关闭)。


四、路由与视图函数

1. 基本路由

@app.route('/about')
def about():
    return '这是关于页面'

2. 动态路由(变量规则)

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

# 指定类型(string, int, float, path, uuid)
@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'文章 ID:{post_id}'

3. 允许的 HTTP 方法

默认只响应 GET,可通过 methods 参数指定:

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return '处理登录表单'
    return '显示登录表单'

五、模板(Jinja2)

Flask 使用 Jinja2 模板引擎,将数据和 HTML 分离。

1. 目录结构

your_project/
├── app.py
└── templates/
    └── index.html

2. 渲染模板

app.py

from flask import render_template

@app.route('/hello/<name>')
def hello_name(name):
    return render_template('hello.html', user_name=name)

templates/hello.html

<!DOCTYPE html>
<html>
<head><title>问候</title></head>
<body>
    <h1>你好,{{ user_name }}!</h1>
</body>
</html>

{{ }} 用于输出变量,Flask 自动对内容进行 HTML 转义,防止 XSS 攻击。

3. 模板中的控制结构

{% if user %}
    <p>欢迎回来,{{ user }}!</p>
{% else %}
    <p>请先登录。</p>
{% endif %}

<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

4. 模板继承

创建基础模板 templates/base.html

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}我的网站{% endblock %}</title>
</head>
<body>
    <nav>导航栏</nav>
    <div class="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

子模板 templates/page.html

{% extends "base.html" %}

{% block title %}子页面标题{% endblock %}

{% block content %}
    <h2>这是子页面的内容</h2>
{% endblock %}

六、静态文件

CSS、JS、图片等放在 static 文件夹下。

your_project/
└── static/
    ├── style.css
    └── logo.png

在模板中引用:

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

七、请求与响应

1. 获取请求数据

导入 request

from flask import request

@app.route('/search')
def search():
    keyword = request.args.get('q', '')   # 获取 URL 查询参数 ?q=xxx
    return f'搜索关键词:{keyword}'

@app.route('/login', methods=['POST'])
def do_login():
    username = request.form['username']    # 获取表单数据
    password = request.form.get('password') # 建议用 get 避免 KeyError
    return f'用户名:{username}'

常用属性:

  • request.args:URL 查询参数(GET)
  • request.form:表单数据(POST)
  • request.json:JSON 数据
  • request.method:请求方法
  • request.headers:请求头
  • request.cookies:Cookie

2. 返回 JSON

from flask import jsonify

@app.route('/api/data')
def data():
    return jsonify({'name': '张三', 'age': 25})

3. 重定向

from flask import redirect, url_for

@app.route('/old-page')
def old_page():
    return redirect(url_for('new_page'))

@app.route('/new-page')
def new_page():
    return '这是新页面'

url_for('视图函数名') 会动态生成 URL,避免硬编码。

4. 错误处理

from flask import abort

@app.route('/private')
def private():
    if not user_logged_in:
        abort(401)          # 返回 401 未授权
    return '私密内容'

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

八、处理表单与安全性

简单登录演示

app.py

from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)
app.secret_key = '请替换为随机字符串'  # session 加密需要

# 假设的合法用户
VALID_USER = {'username': 'admin', 'password': '123456'}

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        if (request.form['username'] == VALID_USER['username'] and
            request.form['password'] == VALID_USER['password']):
            return redirect(url_for('dashboard'))
        else:
            return '登录失败,请重试'
    return render_template('login.html')

@app.route('/dashboard')
def dashboard():
    return '欢迎进入控制面板'

templates/login.html

{% extends "base.html" %}
{% block content %}
<form method="post">
    <label>用户名:<input type="text" name="username"></label><br>
    <label>密码:<input type="password" name="password"></label><br>
    <button type="submit">登录</button>
</form>
{% endblock %}

重要提醒:实际项目中请务必:

  • 使用密码哈希(如 werkzeug.security
  • 防范 CSRF(用 Flask-WTF 扩展)
  • 使用 HTTPS

from flask import make_response, session

# 设置 Cookie
@app.route('/set-cookie')
def set_cookie():
    resp = make_response('Cookie 已设置')
    resp.set_cookie('theme', 'dark', max_age=60*60*24)  # 有效期 1 天
    return resp

# 读取 Cookie
@app.route('/get-cookie')
def get_cookie():
    theme = request.cookies.get('theme', 'light')
    return f'当前主题:{theme}'

# 使用 Session(需设置 app.secret_key)
@app.route('/login-session', methods=['POST'])
def login_session():
    session['user'] = request.form['username']
    return '已登录'

@app.route('/profile')
def profile():
    if 'user' in session:
        return f'欢迎 {session["user"]}'
    return redirect(url_for('login'))

session 是经过加密签名的 Cookie,数据存储在客户端。


十、项目组织

当项目变大时,建议使用 应用工厂模式蓝图(Blueprint) 进行模块化。

简单蓝图示例:

# admin.py
from flask import Blueprint

admin_bp = Blueprint('admin', __name__)

@admin_bp.route('/admin')
def admin_index():
    return '管理后台首页'

在主应用中注册:

from admin import admin_bp
app.register_blueprint(admin_bp)

十一、部署(快速预览)

开发服务器 不能用于生产环境。常见部署方式:

  1. Gunicorn + Nginx(Linux 推荐)
    bash pip install gunicorn gunicorn -w 4 app:app
  2. 云平台:Heroku、PythonAnywhere、Render 等,可直接推送代码自动部署。
  3. Docker 容器化,配合反向代理。

十二、接下来学什么?

  • 数据库集成Flask-SQLAlchemy(ORM)
  • 表单验证Flask-WTF
  • 用户认证Flask-Login
  • RESTful API:结合 flask-restful 或直接用 Flask
  • 测试:使用 pytest
  • 完整项目结构:工厂模式、配置管理(开发/生产/测试)

Flask 的哲学是“用最少的代码带你走入 Web 开发”,而真正深入的功能则通过扩展和你自己的设计来补充。现在就动手写第一个页面,然后逐步添加功能,你会发现 Web 开发其实可以很简单。