Flask框架入门:从安装到模板渲染

说实话,Flask是我个人最喜欢的Python Web框架之一。它轻量、灵活,不像Django那样「全家桶」式的沉重。我在做微服务架构时,经常拿Flask来搭API网关——启动快,配置少,几分钟就能跑起来。

这一章,咱们就从头捋一遍Flask的核心概念。你跟着我走一遍,保证能上手。

1. Flask安装

安装Flask其实就一行命令。但我建议你永远在虚拟环境里操作。为什么?因为不同项目依赖的Flask版本可能不一样,你总不想因为一个项目升级而搞崩另一个吧?

pip install flask

嗯,就这么简单。装完之后,你可以验证一下:

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

如果没报错,说明装好了。我曾经遇到过一个问题——装完Flask后运行报错,结果发现是Python版本太老。Flask 2.0以上需要Python 3.6+,这点要注意。

小提示: 建议用Python 3.8以上版本。我踩过坑,Python 3.6在某些依赖上已经开始报兼容性警告了。

2. 路由与视图函数

路由,说白了就是URL到函数的映射。你访问一个网址,Flask根据你访问的路径,找到对应的函数去处理,然后返回结果。

看个最简单的例子:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, World!'

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

这里 @app.route('/') 就是路由装饰器。它告诉Flask:当用户访问根路径时,执行 home() 这个函数。

路由可以带参数。比如你想做一个用户个人主页:

@app.route('/user/<username>')
def user_profile(username):
    return f'你好,{username}!欢迎来到你的主页。'

你想想看,这样是不是很灵活?不同的用户访问 /user/张三/user/李四,返回的内容就不一样。

路由还支持指定HTTP方法:

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return '处理登录请求'
    return '显示登录页面'
重点: 路由装饰器可以叠加。同一个视图函数可以绑定多个路由,这在做API版本管理时特别有用。

3. 请求与响应对象

Flask把HTTP请求封装成了 request 对象。你从请求里拿数据,全靠它。

我刚开始用Flask时,总记不住怎么取参数。后来总结了一个口诀:

  • URL参数(GET):request.args.get('key')
  • 表单数据(POST):request.form.get('key')
  • JSON数据request.get_json()
  • 请求头request.headers.get('User-Agent')

举个例子,一个处理JSON的API:

from flask import request, jsonify

@app.route('/api/data', methods=['POST'])
def handle_data():
    data = request.get_json()
    if not data:
        return jsonify({'error': '请提供JSON数据'}), 400
    
    name = data.get('name', '匿名')
    return jsonify({'message': f'收到数据,来自{name}'})

响应方面,Flask默认返回字符串。但实际项目中,我们更多用 jsonify() 返回JSON,或者用 make_response() 自定义响应头。

from flask import make_response

@app.route('/custom')
def custom_response():
    resp = make_response('自定义响应', 200)
    resp.headers['X-Custom-Header'] = 'Hello'
    return resp
注意: 我曾经犯过一个低级错误——在POST请求里用 request.args 取数据,结果死活拿不到。记住:POST数据在 request.formrequest.get_json() 里,别搞混了。

4. 模板渲染

Flask默认使用Jinja2模板引擎。模板渲染,就是把HTML模板和动态数据结合起来,生成最终的HTML页面。

首先,在项目根目录下创建 templates 文件夹。Flask会自动去那里找模板文件。

写一个简单的模板 templates/index.html

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

然后在视图函数里渲染它:

from flask import render_template
from datetime import datetime

@app.route('/greet/<name>')
def greet(name):
    return render_template('index.html', 
                          title='欢迎页',
                          name=name,
                          date=datetime.now().strftime('%Y-%m-%d'))

Jinja2模板支持很多高级功能,比如循环、条件判断:

<ul>
{% for item in items %}
    <li>{{ item.name }} - {{ item.price }}元</li>
{% endfor %}
</ul>

{% if user.is_admin %}
    <p>管理员专属内容</p>
{% endif %}

我个人习惯把模板里的逻辑尽量简化。复杂的处理放在视图函数里完成,模板只负责展示。这样代码好维护,也容易调试。

实用技巧: 模板继承可以省很多事。定义一个 base.html 作为布局,其他页面继承它。这样改导航栏、页脚时,只改一个文件就够了。

5. 实战小例子:一个简单的留言板

把上面学的东西串起来,写个迷你留言板:

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

app = Flask(__name__)

messages = []  # 用列表存留言,实际项目会用数据库

@app.route('/')
def index():
    return render_template('board.html', messages=messages)

@app.route('/post', methods=['POST'])
def post_message():
    content = request.form.get('content', '').strip()
    if content:
        messages.append(content)
    return redirect(url_for('index'))

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

模板 board.html

<!DOCTYPE html>
<html>
<head>
    <title>留言板</title>
</head>
<body>
    <h1>留言板</h1>
    <form method="POST" action="/post">
        <input type="text" name="content" placeholder="写点什么...">
        <button type="submit">发布</button>
    </form>
    <hr>
    <h2>已有留言</h2>
    <ul>
    {% for msg in messages %}
        <li>{{ msg }}</li>
    {% endfor %}
    </ul>
</body>
</html>

你看,不到30行代码,一个能用的留言板就出来了。这就是Flask的魅力——简单、直接、高效。

总结一下: Flask的核心就四个东西——路由、视图函数、请求/响应对象、模板渲染。把这四个搞明白,你已经能写大部分Web应用了。下一章我们会深入数据库操作,让数据真正「活」起来。