Flask框架:快速入门指南 – wiki基地


Flask框架:快速入门指南

欢迎来到微型世界的边缘——Flask框架。如果你是Python开发者,对构建Web应用充满兴趣,但又不想一开始就被大型框架的复杂性所压倒,那么Flask正是一个绝佳的起点。它被称为“微框架”,但这并不意味着它功能不足,而是说它核心简洁,高度灵活,你可以根据需要添加各种扩展。

本文将带你从零开始,逐步深入Flask的世界,创建一个简单但功能完整的Web应用。我们将涵盖安装、第一个应用、路由、请求与响应、模板、静态文件、表单处理等核心概念。准备好了吗?让我们开始这段Web开发之旅!

第一章:认识Flask——一个微框架的世界

1.1 什么是Flask?

Flask是一个使用Python编写的轻量级Web服务器网关接口(WSGI)微框架。它由Armin Ronacher领导的Pocoo团队开发。

“微框架”的含义并非指功能少,而是指它的核心非常简单,不包含数据库抽象层、表单验证等组件,这些功能可以通过扩展来添加。这种设计哲学赋予了Flask极高的灵活性,开发者可以自由选择最适合自己项目的工具和库。

Flask基于两个核心库:

  • Werkzeug: 一个WSGI工具包,负责处理请求和响应。
  • Jinja2: 一个功能强大、易于使用的模板引擎,用于生成动态HTML页面。

1.2 为什么选择Flask?

  • 简单易学: 代码结构清晰,API直观,非常适合初学者入门。
  • 高度灵活: 不强制使用特定的工具或技术,开发者可以自由选择数据库、模板引擎(虽然默认是Jinja2,但可以替换)等组件。
  • 丰富的生态: 虽然核心小巧,但Flask拥有一个庞大的社区和大量的第三方扩展,可以轻松添加各种功能,如数据库集成、用户认证、RESTful API支持等。
  • 适合小型到中型项目: 对于API服务、小型网站、快速原型开发等场景,Flask表现出色。通过合理的架构设计和扩展,也能构建复杂的应用。
  • 优秀文档: Flask的官方文档非常完善和清晰。

1.3 Flask与Django的对比(简要)

常常有人将Flask与Django进行比较。简单来说:

  • Django: 一个“全栈”框架,提供了许多内置功能(ORM、管理员界面、表单、模板引擎等),开箱即用,适合快速开发大型、功能丰富的Web应用,尤其注重效率和约定优于配置。
  • Flask: 一个微框架,提供Web开发的基础设施,其他功能通过扩展实现,更灵活,更注重自由选择和定制,适合需要更多控制权或构建特定服务的项目。

选择哪个取决于你的项目需求、团队经验和偏好。对于初学者而言,Flask往往是更容易上手的选择。

第二章:准备环境——安装Flask

在开始之前,你需要确保你的系统中已经安装了Python。建议使用Python 3.6或更高版本。

2.1 虚拟环境的重要性

在Python开发中,强烈建议为每个项目创建一个独立的虚拟环境(Virtual Environment)。虚拟环境可以隔离项目依赖,避免不同项目之间的库版本冲突。

Python 3.3+ 内置了 venv 模块,非常方便使用。

2.2 创建和激活虚拟环境

打开你的终端或命令行工具,导航到你想要创建项目的目录。

创建虚拟环境:

bash
python -m venv .venv

这会在当前目录下创建一个名为 .venv 的文件夹,其中包含了Python解释器的一个独立副本以及用于安装包的 pip 工具。

激活虚拟环境:

  • 在macOS和Linux上:

    bash
    source .venv/bin/activate

  • 在Windows上 (Command Prompt):

    bash
    .venv\Scripts\activate

  • 在Windows上 (PowerShell):

    powershell
    .venv\Scripts\Activate.ps1

激活成功后,你的终端提示符前面会显示虚拟环境的名称,例如 (.venv)

2.3 安装Flask

在虚拟环境激活的状态下,使用 pip 安装Flask:

bash
pip install Flask

pip 会下载并安装Flask及其依赖(Werkzeug和Jinja2)。

你可以通过运行以下命令来验证Flask是否成功安装:

bash
pip show Flask

它会显示Flask的版本和安装路径。

现在,你的环境已经准备就绪,可以开始编写你的第一个Flask应用了!

第三章:你的第一个Flask应用——Hello, World!

让我们来编写一个最简单的Flask应用,它将在浏览器中显示“Hello, World!”。

在你的项目目录中创建一个名为 app.py 的文件(你也可以使用其他名字,例如 main.pyhello.py)。

“`python

app.py

from flask import Flask

创建一个Flask应用实例

name 是当前模块的名称,用于帮助Flask找到资源(如模板和静态文件)

app = Flask(name)

使用装饰器定义一个路由

‘@app.route(‘/’)’ 表示当用户访问网站的根URL (‘/’) 时,

将会触发下面紧跟着的函数

@app.route(‘/’)
def hello_world():
“””
这个函数处理根URL的请求,并返回一个字符串作为响应。
“””
return ‘Hello, World!’

Python脚本的标准入口点

当直接运行这个脚本时,if name == ‘main‘: 下的代码会被执行

if name == ‘main‘:
# 启动Flask内置的开发服务器
# debug=True 开启调试模式:
# 1. 当代码修改时,服务器会自动重启
# 2. 提供了详细的错误追踪页面,方便调试
app.run(debug=True)
“`

3.1 代码解释

  • from flask import Flask: 导入Flask类。
  • app = Flask(__name__): 创建一个Flask应用实例。__name__ 是一个特殊的Python变量,其值是当前模块的名称。Flask使用这个名称来确定应用根目录,以便正确地查找模板和静态文件等资源。
  • @app.route('/'): 这是一个装饰器,它告诉Flask哪个URL应该触发其下的函数。这里,/ 代表网站的根路径。
  • def hello_world():: 这是一个Python函数,它在用户访问根URL时被调用。
  • return 'Hello, World!': 函数返回一个字符串。在Flask中,视图函数的返回值会作为HTTP响应的主体发送给客户端(浏览器)。
  • if __name__ == '__main__':: 这是一个标准的Python习惯用法,确保 app.run() 只在直接运行这个脚本时执行,而不是在作为模块被导入时执行。
  • app.run(debug=True): 启动Flask开发服务器。debug=True 开启调试模式,这在开发阶段非常有用。

3.2 运行你的应用

在激活虚拟环境的终端中,运行你的Python脚本:

bash
python app.py

你应该会看到类似以下的输出:

* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Press Ctrl+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: ...

这表明你的Flask应用已经在本地的 http://127.0.0.1:5000/ 地址上运行起来了。

3.3 在浏览器中查看

打开你的Web浏览器,访问 http://127.0.0.1:5000/

你应该会看到页面上显示:

Hello, World!

恭喜!你已经成功运行了你的第一个Flask应用。

按下 Ctrl+C 可以在终端中停止服务器。

第四章:核心概念详解——路由、请求与响应

Web应用的核心在于如何处理来自客户端(浏览器)的请求,并生成相应的响应。Flask通过路由、请求对象和视图函数来实现这一点。

4.1 路由 (Routing)

路由是将特定的URL路径映射到Python函数的过程。在Flask中,这主要通过 @app.route() 装饰器实现。

你可以定义多个路由和对应的函数:

“`python

app.py (在之前的代码基础上添加)

from flask import Flask

app = Flask(name)

@app.route(‘/’)
def index():
return ‘这是主页’

@app.route(‘/about’)
def about():
return ‘这是关于我们页面’

@app.route(‘/contact’)
def contact():
return ‘这是联系方式页面’

if name == ‘main‘:
app.run(debug=True)
“`

运行这个应用,访问 http://127.0.0.1:5000/http://127.0.0.1:5000/abouthttp://127.0.0.1:5000/contact,你会看到对应函数返回的内容。

4.2 URL变量

路由不仅仅是固定的路径,你还可以在URL中捕获变量。这对于创建动态URL非常有用,比如显示特定用户或文章的页面。

使用 <variable_name> 语法在路由中定义变量:

“`python

app.py (在之前的代码基础上添加)

from flask import Flask

app = Flask(name)

… (前面的路由保留或删除,这里只关注URL变量)

@app.route(‘/user/‘)
def show_user_profile(username):
“””
显示特定用户的个人资料。
是URL中的变量,会被传递给函数。
“””
return f’用户: {username}’

@app.route(‘/post/‘)
def show_post(post_id):
“””
显示特定文章,通过文章ID查找。
指定变量类型为整数。
“””
return f’文章ID: {post_id}’

除了int,常用的类型转换器还有:

string: (默认) 接受任何不包含斜杠的字符串

float: 接受浮点数

path: 接受包含斜杠的字符串

uuid: 接受UUID字符串

if name == ‘main‘:
app.run(debug=True)
“`

运行应用,访问 http://127.0.0.1:5000/user/alice 会显示 用户: alice;访问 http://127.0.0.1:5000/post/123 会显示 文章ID: 123。如果访问 http://127.0.0.1:5000/post/abc,由于类型不匹配,Flask会返回404错误。

4.3 HTTP方法 (HTTP Methods)

Web请求不仅仅是访问URL,还包括请求的类型,即HTTP方法。最常见的方法是 GET (获取数据) 和 POST (提交数据)。其他还有 PUT, DELETE 等。

默认情况下,@app.route() 只响应 GET 请求。你可以通过 methods 参数指定允许的方法:

“`python

app.py (在之前的代码基础上添加)

from flask import Flask, request # 导入request对象

app = Flask(name)

… (其他代码)

@app.route(‘/login’, methods=[‘GET’, ‘POST’])
def login():
if request.method == ‘POST’:
# 处理POST请求,例如从表单获取数据
return ‘处理登录逻辑 (POST)’
else:
# 处理GET请求,例如显示登录表单
return ‘显示登录表单 (GET)’

if name == ‘main‘:
app.run(debug=True)
“`

4.4 请求对象 (request)

flask.request 是一个全局对象(准确地说,是一个线程本地对象),它包含了当前请求的所有信息,如:

  • request.method: 请求方法 (GET, POST等)
  • request.args: URL查询参数(GET请求中 ?key1=value1&key2=value2 部分),返回一个字典状的对象。
  • request.form: 表单提交的数据(POST请求中),返回一个字典状的对象。
  • request.data: 请求体中的原始数据(例如接收JSON或XML时)。
  • request.json: 如果请求头 Content-Typeapplication/json,则解析并返回JSON数据。
  • request.cookies: 请求携带的cookie。
  • request.headers: 请求头信息。
  • request.files: 上传的文件。

要使用 request 对象,需要从 flask 模块导入它。

“`python

app.py (在之前的代码基础上添加)

from flask import Flask, request

app = Flask(name)

… (其他代码)

@app.route(‘/greet’)
def greet():
# 获取查询参数 ‘name’
name = request.args.get(‘name’, ‘Guest’) # 提供默认值 ‘Guest’
return f’Hello, {name}!’

访问 http://127.0.0.1:5000/greet?name=Alice 会显示 “Hello, Alice!”

访问 http://127.0.0.1:5000/greet 会显示 “Hello, Guest!”

if name == ‘main‘:
app.run(debug=True)
“`

我们将在“处理表单”一节中更详细地使用 request.form

4.5 响应 (Response)

视图函数返回的值会被Flask转换为HTTP响应。常见的返回类型包括:

  • 字符串: 最简单的方式,直接作为响应体。
  • 元组: (response_body, status_code, headers)(response_body, status_code)。例如 ('Not Found', 404)。这允许你设置HTTP状态码和额外的响应头。
  • Response 对象: Flask内置的响应类,提供更多控制(不常用,一般用上述方式或辅助函数)。
  • jsonify: 用于返回JSON数据,常用于构建API。需要 from flask import jsonify

“`python

app.py (在之前的代码基础上添加)

from flask import Flask, jsonify

app = Flask(name)

… (其他代码)

@app.route(‘/data’)
def get_data():
data = {‘name’: ‘Example’, ‘value’: 123}
# 使用jsonify将Python字典转换为JSON响应
return jsonify(data)

@app.route(‘/not_found’)
def page_not_found():
# 返回响应体和状态码
return ‘页面不存在’, 404

if name == ‘main‘:
app.run(debug=True)
“`

访问 /data 会得到一个JSON响应;访问 /not_found 会得到一个404状态码的响应页面。

第五章:使用模板——告别硬编码HTML

将HTML代码直接写在Python字符串中是非常不灵活和难以维护的。在Web开发中,通常使用模板引擎将数据填充到预先定义的HTML结构中。Flask默认使用强大的Jinja2模板引擎。

5.1 创建模板文件夹

Flask默认会在应用根目录(app.py 所在的目录)下寻找一个名为 templates 的子文件夹来存放模板文件。

在你的项目目录中创建一个 templates 文件夹:

your_project/
├── .venv/
├── app.py
└── templates/

5.2 编写第一个模板

templates 文件夹中创建一个名为 index.html 的文件:

“`html






我的Flask应用

欢迎来到我的网站!

这是由Flask和Jinja2渲染的页面。


“`

5.3 在视图函数中渲染模板

要渲染模板,你需要从 flask 模块导入 render_template 函数。

修改 app.py

“`python

app.py

from flask import Flask, render_template

app = Flask(name)

@app.route(‘/’)
def index():
# 使用render_template渲染templates/index.html文件
return render_template(‘index.html’)

… (其他路由可以继续添加)

if name == ‘main‘:
app.run(debug=True)
“`

运行应用并访问 http://127.0.0.1:5000/,你会看到 index.html 的内容被渲染出来。

5.4 向模板传递数据

模板真正的强大之处在于能够接收Python变量,并在HTML中显示它们。你可以在 render_template 函数中以关键字参数的形式传递变量:

“`python

app.py

from flask import Flask, render_template

app = Flask(name)

@app.route(‘/’)
def index():
title = “主页”
heading = “欢迎!”
items = [“苹果”, “香蕉”, “橙子”]
# 将Python变量传递给模板
return render_template(‘index.html’, title=title, heading=heading, items=items)

if name == ‘main‘:
app.run(debug=True)
“`

修改 templates/index.html,使用 Jinja2 语法来访问这些变量和进行控制流操作:

“`html







{{ title }} – 我的Flask应用


{{ heading }}

这是一个列表:


    {% for item in items %}

  • {{ item }}
  • {% endfor %}

{% if items %}

列表不为空。

{% else %}

列表为空。

{% endif %}

当前年份: {{ 2023 }}

{# 也可以直接显示字面量 #}


“`

运行应用并刷新页面,你会看到变量的值被正确地填充到模板中,列表也被遍历显示。

Jinja2常用语法回顾:

  • {{ variable }}: 用于输出变量或表达式的值。
  • {% control_structure %}: 用于控制结构,如 for 循环 ({% for %} / {% endfor %}),if 条件判断 ({% if %} / {% elif %} / {% else %} / {% endif %})。
  • {# comment #}: 用于模板中的注释,不会渲染到最终HTML中。

5.5 模板继承 (Template Inheritance)

对于大型项目,很多页面会有相同的结构(如头部、底部、导航栏)。模板继承可以帮助你避免重复代码。

  1. 创建基础模板:templates 文件夹中创建一个基础布局文件,例如 base.html。它包含页面共享的结构,并定义“块”(block),子模板可以覆盖这些块。

    “`html

    <!DOCTYPE html>



    {% block title %}我的网站{% endblock %} – Flask
    {# 可以在这里链接共享的CSS文件 #}

    网站标题

    <main>
        {# 这是主要内容的块,子模板将在这里插入内容 #}
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2023 我的Flask应用</p>
    </footer>
    



    “`

  2. 创建子模板: 创建其他页面模板,使用 {% extends 'base.html' %} 来继承基础模板,并使用 {% block block_name %} / {% endblock %} 来填充或覆盖基础模板中定义的块。

    修改 templates/index.html 使用继承:

    “`html

    {% extends ‘base.html’ %} {# 继承 base.html #}

    {% block title %}{{ title }}{% endblock %} {# 覆盖 base.html 中的 title 块 #}

    {% block content %} {# 填充 base.html 中的 content 块 #}

    {{ heading }}

    <p>这是一个列表:</p>
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    {% if items %}
        <p>列表不为空。</p>
    {% else %}
        <p>列表为空。</p>
    {% endif %}
    

    {% endblock %}
    “`

    添加一个新的关于页面 templates/about.html:

    “`html

    {% extends ‘base.html’ %}

    {% block title %}关于我们{% endblock %}

    {% block content %}

    关于我们

    这是关于我们页面的内容。

    {% endblock %}
    “`

  3. 修改 app.py 渲染子模板:

    “`python

    app.py

    from flask import Flask, render_template, url_for # 导入url_for

    app = Flask(name)

    @app.route(‘/’)
    def index():
    title = “主页”
    heading = “欢迎!”
    items = [“苹果”, “香蕉”, “橙子”]
    return render_template(‘index.html’, title=title, heading=heading, items=items)

    @app.route(‘/about’)
    def about():
    return render_template(‘about.html’)

    url_for 函数的使用:

    在模板中,url_for(‘index’) 会生成 ‘/’

    url_for(‘about’) 会生成 ‘/about’

    url_for(‘show_user_profile’, username=’alice’) 会生成 ‘/user/alice’

    url_for(‘static’, filename=’style.css’) 会生成 ‘/static/style.css’ (下一节会解释)

    url_for 非常重要,因为它能处理URL的变化,并且会自动处理URL参数的生成

    if name == ‘main‘:
    app.run(debug=True)
    “`

现在,访问 //about 页面,它们都将继承 base.html 的结构,但分别显示各自的内容和标题。

第六章:处理静态文件——CSS, JS和图片

Web应用不仅需要动态生成的HTML,还需要提供静态文件,如CSS样式表、JavaScript脚本和图片。

6.1 创建静态文件夹

与模板类似,Flask默认在应用根目录下寻找一个名为 static 的子文件夹来存放静态文件。

在你的项目目录中创建一个 static 文件夹:

your_project/
├── .venv/
├── app.py
├── templates/
│ ├── base.html
│ ├── index.html
│ └── about.html
└── static/
└── style.css {# 例如创建一个CSS文件 #}

6.2 编写一个简单的CSS文件

static 文件夹中创建一个 style.css 文件:

“`css
/ static/style.css /
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f4;
}

header {
background-color: #333;
color: white;
padding: 10px 0;
text-align: center;
}

nav a {
color: white;
margin: 0 10px;
text-decoration: none;
}

main {
margin-top: 20px;
padding: 15px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

footer {
margin-top: 20px;
text-align: center;
color: #666;
}
“`

6.3 在模板中链接静态文件

在模板中,使用 url_for() 函数并指定 'static' 端点以及文件的路径作为 filename 参数来生成静态文件的URL。

templates/base.html<head> 部分,我们已经添加了链接:

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

url_for('static', filename='style.css') 会生成 /static/style.css 这样的URL。Flask开发服务器会自动处理 /static/ 下的请求,并从 static 文件夹中查找对应文件。

运行应用并刷新页面,你会看到页面应用了 style.css 中的样式。

你可以将其他静态文件(如 script.js, logo.png 等)放在 static 文件夹中,并在模板中使用 url_for('static', filename='path/to/your_file') 来引用它们。

第七章:处理表单——获取用户输入

Web应用经常需要从用户那里获取输入,例如通过表单。Flask使得处理表单提交变得相对容易。

7.1 创建一个包含表单的模板

创建一个新的模板文件,例如 templates/form.html

“`html

{% extends ‘base.html’ %}

{% block title %}提交信息{% endblock %}

{% block content %}

提交信息

{# form 标签的 method="POST" 指定使用POST方法提交表单 #}
{# action="{{ url_for('submit_form') }}" 指定表单提交到哪个URL #}
<form method="POST" action="{{ url_for('submit_form') }}">
    <div>
        <label for="name">姓名:</label>
        <input type="text" id="name" name="name" required>
    </div>
    <br>
    <div>
        <label for="message">留言:</label>
        <textarea id="message" name="message" required></textarea>
    </div>
    <br>
    <button type="submit">提交</button>
</form>

{% endblock %}
“`

注意 form 标签的 method="POST"action="{{ url_for('submit_form') }}"url_for('submit_form') 会生成一个URL,该URL对应于我们稍后在 app.py 中定义的名为 submit_form 的视图函数。

7.2 创建处理表单的视图函数

我们需要两个视图函数:一个用于显示表单(GET请求),另一个用于接收和处理表单提交的数据(POST请求)。

修改 app.py

“`python

app.py

from flask import Flask, render_template, request, redirect, url_for # 导入request和redirect

app = Flask(name)

… (之前的路由和代码)

@app.route(‘/submit’, methods=[‘GET’, ‘POST’])
def submit_form():
if request.method == ‘POST’:
# 如果是POST请求,从request.form中获取表单数据
name = request.form.get(‘name’) # 获取name字段的值
message = request.form.get(‘message’) # 获取message字段的值

    # 可以在这里处理数据,例如保存到数据库或进行其他操作
    print(f"收到提交:姓名 - {name}, 留言 - {message}") # 简单打印到控制台

    # 处理完数据后,通常会重定向到另一个页面,避免用户刷新页面重复提交
    # url_for('success_page') 会生成成功页面的URL
    return redirect(url_for('success_page'))
else:
    # 如果是GET请求,渲染表单页面
    return render_template('form.html')

@app.route(‘/success’)
def success_page():
# 简单的成功提示页面
return ‘表单提交成功!’

if name == ‘main‘:
app.run(debug=True)
“`

7.3 代码解释

  • from flask import ..., request, redirect, url_for: 导入 request 对象用于访问请求数据,redirect 函数用于重定向到另一个URL,url_for 用于生成URL。
  • @app.route('/submit', methods=['GET', 'POST']): 定义 /submit 路由,允许GET和POST方法。GET请求用于显示表单,POST请求用于接收提交。
  • if request.method == 'POST':: 检查当前请求是否是POST方法。
  • name = request.form.get('name'): request.form 是一个类字典对象,包含POST提交的表单数据。.get('name') 安全地获取名为 name 的输入字段的值。如果该字段不存在,.get() 返回 None,而不是抛出错误。
  • print(...): 在服务器控制台打印收到的数据(在实际应用中你会在这里处理数据)。
  • return redirect(url_for('success_page')): 处理完POST请求后,使用 redirect() 函数将用户重定向到 /success URL(由 url_for('success_page') 生成)。重定向是处理POST请求后的标准做法,称为“POST/Redirect/GET”模式,可以防止用户刷新页面时浏览器提示重新提交表单。
  • else:: 如果请求不是POST(即GET请求),则渲染 form.html 模板显示表单。
  • @app.route('/success'): 定义一个简单的成功页面的路由。

7.4 运行并测试表单

运行应用。访问 http://127.0.0.1:5000/submit 会显示表单页面。填写信息并提交,你会在终端看到打印输出,并且浏览器会自动重定向到 /success 页面。

第八章:构建更复杂的应用结构(初探)

对于简单的应用,将所有代码放在一个 app.py 文件中是可以接受的。但随着应用的增长,一个文件会变得非常庞大和难以管理。将应用组织成模块或使用Blueprint是更好的实践。

对于快速入门,我们先演示一个简单的文件分割方式。更高级的模块化(如使用Blueprints)是下一步学习的内容。

8.1 简单的文件分割

你可以将路由和视图函数放在单独的文件中,并在主应用文件中导入和注册。

  1. 创建 views.py 文件: 在项目根目录创建 views.py 文件。

    “`python

    views.py

    from flask import render_template, request, redirect, url_for

    注意:这里不能直接使用 app 实例,因为 app 在 app.py 中定义。

    我们将在 app.py 中导入这些函数,并使用 app.route 装饰器注册它们。

    def index():
    title = “主页”
    heading = “欢迎!”
    items = [“苹果”, “香蕉”, “橙子”]
    return render_template(‘index.html’, title=title, heading=heading, items=items)

    def about():
    return render_template(‘about.html’)

    def submit_form():
    if request.method == ‘POST’:
    name = request.form.get(‘name’)
    message = request.form.get(‘message’)
    print(f”收到提交:姓名 – {name}, 留言 – {message}”)
    return redirect(url_for(‘success_page’))
    else:
    return render_template(‘form.html’)

    def success_page():
    return ‘表单提交成功!’

    你可以定义更多视图函数…

    “`

  2. 修改 app.py: 导入 views 文件中的函数,并使用 app.route 装饰器注册它们。

    “`python

    app.py

    from flask import Flask
    from views import index, about, submit_form, success_page # 从 views.py 导入函数

    app = Flask(name)

    使用导入的函数注册路由

    app.add_url_rule(‘/’, ‘index’, index) # endpoint ‘index’, view_func index
    app.add_url_rule(‘/about’, ‘about’, about) # endpoint ‘about’, view_func about
    app.add_url_rule(‘/submit’, ‘submit_form’, submit_form, methods=[‘GET’, ‘POST’]) # endpoint ‘submit_form’
    app.add_url_rule(‘/success’, ‘success_page’, success_page) # endpoint ‘success_page’

    更好的方式是直接在 views.py 中定义函数后,

    在 app.py 中导入整个 views 模块或函数,

    然后在 app.py 中使用 @app.route() 装饰器来装饰这些导入的函数。

    例如:

    from flask import Flask

    from views import index, about, submit_form, success_page

    app = Flask(name)

    @app.route(‘/’)

    def index_route(): # 使用不同的函数名避免冲突,或者确保导入的函数名不与本地变量冲突

    return index() # 调用 views.py 中的 index 函数

    @app.route(‘/about’)

    def about_route():

    return about()

    # … 其他路由 …

    # 或者更直接的方式,如果你在 views.py 中定义了 app 实例并使用了 @app.route

    # 但在大型应用中,通常使用 Blueprints

    # 最推荐的方式是使用 Blueprint (后续学习)

    # 对于简单的文件分割,我们可以直接在 app.py 中导入函数并应用装饰器:

    删除上面的 add_url_rule 代码,改用装饰器方式更常见

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

    app = Flask(name)

    # 直接导入函数并在主 app.py 中装饰

    # from views import index as views_index, about as views_about, \

    submit_form as views_submit_form, success_page as views_success_page

    @app.route(‘/’)

    def index():

    return views_index()

    @app.route(‘/about’)

    def about():

    return views_about()

    @app.route(‘/submit’, methods=[‘GET’, ‘POST’])

    def submit_form():

    return views_submit_form()

    @app.route(‘/success’)

    def success_page():

    return views_success_page()

    然而,最简单的文件分割是在 app.py 中直接导入并装饰 views 文件中的函数

    重新组织一下 app.py 代码,使其更清晰:

    app.py

    from flask import Flask

    创建应用实例

    app = Flask(name)

    导入视图函数,并在导入后立即使用装饰器

    或者在一个函数中注册,但在小应用中直接在顶部注册更常见

    确保导入时不会因为循环导入而出错(小应用一般不会)

    from views import index, about, submit_form, success_page

    使用装饰器注册路由

    @app.route(‘/’)
    def home_route(): # 使用不同的函数名来区分,或者直接使用导入的函数名(不推荐,易混淆)
    return index() # 调用views.py中的index函数

    @app.route(‘/about’)
    def about_route():
    return about()

    @app.route(‘/submit’, methods=[‘GET’, ‘POST’])
    def submit_form_route():
    return submit_form() # views_submit_form()

    @app.route(‘/success’)
    def success_page_route():
    return success_page() # views_success_page()

    在小型应用中,更常见的做法是直接在 app.py 中导入并装饰

    比如:

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

    app = Flask(name)

    from views import index, about, submit_form, success_page # 导入函数

    app.add_url_rule(‘/’, ‘index’, index)

    app.add_url_rule(‘/about’, ‘about’, about)

    app.add_url_rule(‘/submit’, ‘submit_form’, submit_form, methods=[‘GET’, ‘POST’])

    app.add_url_rule(‘/success’, ‘success_page’, success_page)

    if name == ‘main‘:

    app.run(debug=True)

    回到最开始的思路,直接在 app.py 中导入 views 并注册

    这种方式避免在 views 中依赖 app 实例,也避免在 app 中重命名函数

    推荐使用 add_url_rule 函数来注册导入的函数:

    app.py

    from flask import Flask

    创建应用实例

    app = Flask(name)

    导入视图函数

    from views import index, about, submit_form, success_page

    注册路由

    app.add_url_rule(rule, endpoint, view_func, **options)

    rule: URL规则

    endpoint: 路由的名称,用于 url_for 函数

    view_func: 处理请求的函数

    app.add_url_rule(‘/’, ‘index’, index)
    app.add_url_rule(‘/about’, ‘about’, about)
    app.add_url_rule(‘/submit’, ‘submit_form’, submit_form, methods=[‘GET’, ‘POST’])
    app.add_url_rule(‘/success’, ‘success_page’, success_page)

    另一种常见模式是创建 create_app() 工厂函数 (推荐用于大型应用和测试)

    def create_app():

    app = Flask(name)

    # 配置 app

    # 注册路由、Blueprint、扩展等

    from views import index, about, submit_form, success_page

    app.add_url_rule(‘/’, ‘index’, index)

    app.add_url_rule(‘/about’, ‘about’, about)

    app.add_url_rule(‘/submit’, ‘submit_form’, submit_form, methods=[‘GET’, ‘POST’])

    app.add_url_rule(‘/success’, ‘success_page’, success_page)

    return app

    app = create_app() # 创建应用实例

    if name == ‘main‘:

    app.run(debug=True)

    对于快速入门,使用 app.add_url_rule 注册导入的函数是简单有效的方法。

    if name == ‘main‘:
    app.run(debug=True)
    “`

这种结构将视图逻辑与应用实例的创建和配置分离开,使得代码更易读和组织。随着项目变大,你会进一步学习Blueprint,它是Flask官方推荐的模块化应用方式。

第九章:调试 Flask 应用

在开发过程中,错误是不可避免的。Flask提供了良好的调试支持:

  • 调试模式 (debug=True): 在开发服务器运行时,设置 app.run(debug=True) 可以获得:
    • 自动重载: 修改代码后,服务器会自动重启。
    • 交互式调试器: 当发生未处理的异常时,浏览器会显示一个交互式的Web界面,你可以在其中查看堆栈跟踪、检查变量、甚至执行Python代码。这是一个非常强大的工具!出于安全考虑,生产环境绝对不能开启调试模式。
  • 日志: 使用Python标准的 logging 模块在你的代码中记录信息,帮助追踪问题。
  • 打印输出: 简单的 print() 语句会输出到运行Flask应用的终端。

当在浏览器中遇到交互式调试器时,你需要输入一个PIN码才能完全访问其功能(PIN码在终端输出中可以看到)。这是为了防止其他人访问你的调试器。

第十章:部署考虑(简要)

app.run() 启动的服务器是Flask自带的开发服务器,它方便开发和调试,但不适合用于生产环境。生产环境需要更健壮、性能更高的Web服务器。

在生产环境中部署Flask应用通常需要:

  1. 一个WSGI服务器: 例如 Gunicorn, uWSGI。这些服务器负责接收来自客户端的请求,并将请求传递给你的Flask应用。
  2. 一个前端Web服务器 (可选但推荐): 例如 Nginx, Apache。它们可以处理静态文件、负载均衡、SSL加密等,并将动态请求转发给WSGI服务器。
  3. 进程管理工具: 例如 Supervisor, systemd,用于确保你的WSGI服务器始终运行。

部署是一个更复杂的阶段,超出了快速入门的范围。掌握了基础知识后,你可以查阅Flask官方文档或其他资源,学习如何使用Gunicorn或uWSGI等工具部署你的应用。

第十一章:下一步去哪里?

恭喜你!你已经掌握了Flask的核心基础知识,能够构建一个简单的Web应用了。这仅仅是一个开始,Flask的世界还有很多值得探索:

  • Flask扩展: 学习使用官方推荐或流行的第三方扩展来添加功能,例如:
    • Flask-SQLAlchemy: 集成SQLAlchemy ORM,简化数据库操作。
    • Flask-Migrate: 数据库迁移工具。
    • Flask-Login: 处理用户会话管理和认证。
    • Flask-WTF: 集成WTForms库,简化表单创建、验证和处理。
    • Flask-RESTful 或 Flask-RESTx: 构建RESTful API。
  • Blueprint: 学习如何使用Blueprint来组织更大型的应用,将应用分解为可重用的组件。
  • 上下文 (Contexts): 深入理解请求上下文和应用上下文,以及它们如何工作。
  • 信号 (Signals): 了解如何在应用中发送和接收信号,以实现解耦。
  • 错误处理: 更详细地学习如何定制错误页面(如404, 500)。
  • 测试: 学习如何为你的Flask应用编写单元测试和集成测试。
  • 安全: 了解常见的Web安全威胁(XSS, CSRF等)以及Flask和其扩展提供的防护措施。
  • 异步编程: 学习如何在Flask中使用异步特性(例如 ASGI 服务器和异步视图函数)。
  • 部署: 详细学习如何在不同的环境中部署你的Flask应用。

总结

Flask以其简洁和灵活性,为Python开发者提供了一条构建Web应用的愉快路径。从基本的“Hello, World!”到处理请求、渲染模板、提供静态文件和处理表单,你已经掌握了快速启动一个Web项目所需的关键技能。

记住,实践是最好的老师。尝试修改本文中的代码,添加新的页面,实现新的功能。查阅Flask官方文档是解决问题的最佳途径。

祝你在Flask的Web开发之旅中一切顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部