Python Flask Web 开发入门 – wiki基地


Python Flask Web 开发入门:从零开始构建你的第一个Web应用

欢迎来到Python世界里简洁而强大的Web开发框架——Flask!如果你已经掌握了Python基础,并渴望将你的技能应用到Web开发领域,那么Flask绝对是一个绝佳的起点。它是一个微框架,这意味着它提供了构建Web应用所需的核心功能,同时保持了极大的灵活性和扩展性,让你能够自由选择所需的工具和库。

本文将带你从零开始,一步步深入了解Flask的基础知识,并指导你构建一个简单的Web应用。我们将涵盖环境搭建、核心概念、模板引擎、表单处理以及项目结构等内容。

1. 为什么选择 Flask?

在深入学习之前,让我们先了解一下为什么Flask是一个值得学习的Web框架:

  • 微框架 (Microframework): Flask的核心非常精简,不包含ORM(对象关系映射)、表单验证等重量级组件。这使得它非常轻量级,启动速度快,并且给了开发者极大的选择自由,可以根据项目需求集成第三方库。
  • 易学易用: Flask的API设计简洁直观,上手非常容易。对于有Python基础的开发者来说,学习曲线非常平缓。
  • 灵活性高: 你可以轻松地构建小型应用、API服务,甚至通过集成各种扩展来构建大型复杂应用。
  • 强大的社区和丰富的扩展: Flask拥有一个活跃的社区,提供了大量的第三方扩展(Flask Extensions),涵盖了数据库集成、用户认证、RESTful API构建、管理后台等方面,可以帮助你快速开发。
  • 基于 Werkzeug 和 Jinja2: Flask内部使用了两个成熟且强大的库:WSGI工具集 Werkzeug 负责处理底层的HTTP请求和响应,而 Jinja2 则是功能强大且易于使用的模板引擎。

2. 环境搭建

在开始编写Flask应用之前,我们需要搭建好开发环境。强烈建议使用虚拟环境来隔离不同项目之间的依赖。

步骤 1: 安装 Python

确保你的系统已经安装了 Python 3.6 或更高版本。你可以在终端或命令行中运行 python --versionpython3 --version 来检查。如果未安装,请访问 Python官网 下载并安装。

步骤 2: 创建并激活虚拟环境

虚拟环境可以确保你的项目依赖与系统中其他的 Python 项目隔离开,避免版本冲突。Python 3.3+ 内置了 venv 模块,无需额外安装。

打开终端或命令行,导航到你想要创建项目的目录,然后执行以下命令:

“`bash

创建一个名为 ‘myflaskapp-venv’ 的虚拟环境

python -m venv myflaskapp-venv
“`

这将会在当前目录下创建一个名为 myflaskapp-venv 的文件夹,其中包含了独立的 Python 环境。

接下来,需要激活虚拟环境:

  • macOS/Linux:
    bash
    source myflaskapp-venv/bin/activate

    激活后,你的终端提示符前会显示虚拟环境的名称 (myflaskapp-venv)
  • Windows:
    cmd
    myflaskapp-venv\Scripts\activate

    激活后,你的命令行提示符前会显示虚拟环境的名称 (myflaskapp-venv)

步骤 3: 安装 Flask

虚拟环境激活后,使用 pip 来安装 Flask:

bash
pip install Flask

等待安装完成。现在,你的虚拟环境中就已经成功安装了 Flask。

你可以使用 pip list 命令查看当前虚拟环境中安装的库,应该能看到 Flask 及其依赖(如 Werkzeug, Jinja2, MarkupSafe, itsdangerous, click)。

3. 你的第一个 Flask 应用:”Hello, World!”

好了,环境已经准备就绪,让我们来编写最简单的 Flask 应用——一个在浏览器中显示 “Hello, World!” 的页面。

在你的项目目录下(与 myflaskapp-venv 同级),创建一个新的 Python 文件,命名为 app.py

“`python

app.py

from flask import Flask

创建一个 Flask 应用实例

name 是一个特殊的 Python 变量,代表当前模块的名称。

Flask 使用它来确定应用的根目录,以便找到资源文件(如模板和静态文件)。

app = Flask(name)

定义一个路由(Route)

@app.route(‘/’) 是一个装饰器,它告诉 Flask 当用户访问应用的根 URL ‘/’ 时,

执行下面的函数。

@app.route(‘/’)
def index():
# 这个函数被称为视图函数(View Function)
# 它返回一个字符串,Flask 会将其作为 HTTP 响应体发送给浏览器
return ‘Hello, World!’

运行应用

if name == ‘main‘: 是 Python 的标准用法,

确保只有在直接运行此脚本时才执行 app.run()。

debug=True 开启调试模式,这将在开发过程中提供有用的信息,

比如当代码修改时自动重启服务器,以及在浏览器中显示错误堆栈。

注意:不要在生产环境中使用 debug=True。

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

保存 app.py 文件。

现在,回到你的终端或命令行,确保虚拟环境已激活,然后运行你的应用:

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
* Restarting with stat
* Debugger is active!
* Debugger PIN: 123-456-789

这表明 Flask 开发服务器已经在本地的 5000 端口上运行起来了。

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

你将会在页面上看到 “Hello, World!”。

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

4. 理解核心概念

让我们更深入地理解上面代码中的几个核心概念:

  • Flask 实例 (app = Flask(__name__)): 这是你的 Web 应用的核心。所有的路由、配置等都注册在这个实例上。
  • 路由 (Routing): @app.route('/') 装饰器将特定的 URL 路径(例如 /, /about, /users)映射到 Python 函数。当用户访问该 URL 时,相应的函数就会被调用。
  • 视图函数 (View Function):@app.route() 装饰器关联的 Python 函数。它负责处理用户的请求,并返回一个响应(通常是 HTML 字符串、JSON 或一个 Response 对象)。
  • 开发服务器 (app.run()): Flask 提供了一个简单的内置开发服务器,用于开发和测试。它不是为生产环境设计的,因为它性能有限且缺乏安全性。
  • 调试模式 (debug=True): 在开发模式下非常有用。开启后,当你的代码发生错误时,浏览器会显示详细的错误信息,并且当你修改代码并保存时,服务器会自动重新加载,无需手动重启。

更多路由示例:

你可以在同一个应用中定义多个路由和视图函数:

“`python

… (前面的代码不变)

@app.route(‘/about’)
def about():
return ‘This is the About page.’

@app.route(‘/contact’)
def contact():
return ‘Contact us at [email protected]

… (后面的代码不变)

“`

访问 http://127.0.0.1:5000/abouthttp://127.0.0.1:5000/contact 将会看到对应的页面内容。

动态路由:

Flask 允许你定义带有变量的路由,以便处理像用户 ID 或文章 slug 这样的动态数据。

“`python

… (前面的代码不变)

@app.route(‘/user/‘)
def show_user_profile(username):
# username 变量会自动从 URL 中捕获并作为参数传递给函数
return f’User: {username}’

@app.route(‘/post/‘)
def show_post(post_id):
# 表示捕获一个整数,并将其命名为 post_id
return f’Post ID: {post_id}’

… (后面的代码不变)

“`

访问 http://127.0.0.1:5000/user/alice 将显示 “User: alice”,访问 http://127.0.0.1:5000/post/123 将显示 “Post ID: 123″。如果你访问 http://127.0.0.1:5000/post/abc,Flask 会返回一个 404 Not Found 错误,因为 abc 不是一个整数。

Flask 提供了一些内置的变量类型转换器,如 <string> (默认), <int>, <float>, <path> (包含斜杠), <uuid>

5. 处理 HTTP 方法

Web 应用不仅仅是展示信息,还需要处理用户提交的数据,例如表单提交。HTTP 定义了多种请求方法,最常见的有 GET (获取数据) 和 POST (提交数据)。

默认情况下,Flask 路由只响应 GET 请求。你可以通过在 @app.route() 装饰器中指定 methods 参数来允许其他方法。

“`python
from flask import Flask, request # 需要导入 request 对象

app = Flask(name)

@app.route(‘/login’, methods=[‘GET’, ‘POST’])
def login():
if request.method == ‘POST’:
# 如果是 POST 请求,处理提交的表单数据
username = request.form.get(‘username’) # 使用 .get() 更安全,如果字段不存在返回 None
password = request.form.get(‘password’)
# 在这里进行用户认证等逻辑
return f’Username: {username}, Password: {password}’
else:
# 如果是 GET 请求,显示登录表单
return ”’

”’

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

在上面的例子中,/login 路由可以响应 GETPOST 请求。
* 当用户通过浏览器直接访问 /login 时,是一个 GET 请求,会显示 HTML 表单。
* 当用户填写表单并点击提交按钮时(如果表单的 method="post"),浏览器会发送一个 POST 请求到 /login,此时 request.method 会是 'POST',我们就可以通过 request.form 来访问表单中提交的数据。request.form 是一个字典样的对象,包含表单字段名和对应的值。

request 对象包含了所有关于当前请求的信息,例如请求方法 (request.method)、表单数据 (request.form)、URL 参数 (request.args)、文件上传 (request.files)、请求头 (request.headers) 等等。

6. 使用模板引擎 Jinja2

直接在视图函数中返回包含大量 HTML 的字符串是非常繁琐且难以维护的。Flask 使用 Jinja2 作为默认的模板引擎,它允许我们将 HTML 代码与 Python 逻辑分离。

步骤 1: 创建 templates 文件夹

在你的 app.py 文件所在的同一目录下,创建一个名为 templates 的新文件夹。Flask 默认会在这个文件夹中查找模板文件。

步骤 2: 创建 HTML 模板文件

templates 文件夹中创建一个 HTML 文件,例如 index.html

“`html







Flask 入门

你好,{{ name }}!

这是使用 Jinja2 模板渲染的页面。

{% if items %}

项目列表:

    {% for item in items %}

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

{% else %}

目前没有项目。

{% endif %}

“`

Jinja2 基本语法:

  • {{ ... }}: 用于输出变量的值或表达式的结果。
  • {% ... %}: 用于执行控制结构,如 if 语句、for 循环等。
  • {# ... #}: 用于添加注释。

步骤 3: 在视图函数中渲染模板

修改 app.py 文件,使用 render_template 函数来渲染模板。

“`python
from flask import Flask, render_template # 需要导入 render_template 函数

app = Flask(name)

@app.route(‘/’)
def index():
# 定义一些要在模板中使用的变量
user_name = “访客”
my_items = [“苹果”, “香蕉”, “橙子”]
# 使用 render_template 函数渲染 templates/index.html 文件
# 可以将 Python 变量作为关键字参数传递给模板
return render_template(‘index.html’, name=user_name, items=my_items)

@app.route(‘/hello/‘)
def hello(name):
# 渲染模板,并将动态路由中的 name 变量传递给模板
return render_template(‘index.html’, name=name, items=[]) # 传递一个空列表

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

重新运行 python app.py。现在访问 http://127.0.0.1:5000 将看到一个更友好的页面,显示 “你好,访客!” 和项目列表。访问 http://127.0.0.1:5000/hello/张三 将显示 “你好,张三!”。

模板继承:

对于大型应用,页面通常有共同的部分,如头部、尾部、导航栏。模板继承允许你定义一个基础模板,其他模板可以继承它并覆盖或填充特定的块。

创建 templates/base.html:

“`html







{% block title %}我的应用{% endblock %} {# 定义一个可被子模板覆盖的块 #} {# 引入静态文件,后面会讲 #}

我的应用


{% block content %} {# 定义主要内容块 #}
{% endblock %}

© 2023 我的应用


“`

修改 templates/index.html 继承 base.html:

“`html

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

{% block title %}首页 – {{ super() }}{% endblock %} {# 覆盖 title 块,并保留父模板的内容 #}

{% block content %} {# 填充 content 块 #}

你好,{{ name }}!

这是使用 Jinja2 模板渲染的页面。

{% if items %}
    <h2>项目列表:</h2>
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
{% else %}
    <p>目前没有项目。</p>
{% endif %}

{% endblock %}
“`

现在,index.html 会包含 base.html 的结构,并且在 content 块的位置显示自己的内容。这大大减少了代码重复。

7. 静态文件

Web 应用通常需要引入 CSS 文件、JavaScript 文件和图片等静态资源。Flask 约定将这些文件放在一个名为 static 的文件夹中。

步骤 1: 创建 static 文件夹

在你的项目根目录(与 app.pytemplates 同级)创建一个名为 static 的文件夹。

步骤 2: 创建 CSS 文件

static 文件夹中创建一个子文件夹,例如 css,然后在 css 文件夹中创建一个文件,例如 style.css

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

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: 20px;
background-color: white;
border-radius: 8px;
}
“`

步骤 3: 在模板中引用静态文件

在你的模板文件(例如 base.html)中使用 url_for 函数来生成静态文件的 URL。url_for 函数第一个参数是端点名称(对于静态文件总是 'static'),第二个参数 filename 指定静态文件在 static 文件夹中的路径。

“`html



{% block title %}我的应用{% endblock %}
{# 引入 static/css/style.css 文件 #}
“`

重新运行应用,访问页面时,你应该能看到应用了 style.css 样式的页面。

使用 url_for 的好处是,如果将来你的应用部署在不同的 URL 路径下,或者你改变了静态文件的位置(在 static 文件夹内),你只需要修改一个地方(Flask 配置或文件结构),而不需要手动修改模板中所有的 URL 链接。

8. 处理表单提交

在第5节中,我们简要介绍了如何处理 POST 请求和访问 request.form。现在,让我们结合模板来创建一个更完整的表单处理示例。

假设我们想创建一个简单的留言板,允许用户提交留言。

步骤 1: 创建留言板模板 (templates/message_board.html)

“`html
{% extends ‘base.html’ %}

{% block title %}留言板 – {{ super() }}{% endblock %}

{% block content %}

留言板

<h2>提交新留言</h2>
{# 表单 method="post" 将数据作为 POST 请求发送到当前 URL '/' #}
<form method="post">
    <p>
        <label for="author">姓名:</label><br>
        <input type="text" id="author" name="author" required>
    </p>
    <p>
        <label for="message">留言:</label><br>
        <textarea id="message" name="message" rows="4" cols="50" required></textarea>
    </p>
    <p>
        <input type="submit" value="提交留言">
    </p>
</form>

<hr>

<h2>所有留言</h2>
{# 假设 messages 是一个包含留言字典的列表 #}
{% if messages %}
    <ul>
        {% for message in messages %}
            <li>
                <strong>{{ message.author }}</strong> 说:
                <p>{{ message.content }}</p>
            </li>
        {% endfor %}
    </ul>
{% else %}
    <p>还没有留言。</p>
{% endif %}

{% endblock %}
“`

步骤 2: 修改 app.py 处理表单和渲染模板

我们将把留言存储在一个简单的列表中(在实际应用中会使用数据库)。

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

app = Flask(name)

简单的列表来存储留言(非持久化)

messages = []

@app.route(‘/’, methods=[‘GET’, ‘POST’])
def message_board():
if request.method == ‘POST’:
# 处理 POST 请求:获取表单数据并添加到 messages 列表
author = request.form.get(‘author’)
content = request.form.get(‘message’)

    if author and content: # 确保字段不为空
        messages.append({'author': author, 'content': content})
        # 重定向到同一个页面,以避免刷新时重复提交表单
        # url_for('message_board') 根据函数名生成 '/' 的 URL
        return redirect(url_for('message_board'))
    else:
        # 可以处理表单验证失败的情况
        pass # 简单示例,忽略验证失败

# 处理 GET 请求:渲染留言板模板,并传递当前的 messages 列表
return render_template('message_board.html', messages=messages)

@app.route(‘/about’) # 保持之前的 about 路由
def about():
return render_template(‘base.html’) # 可以使用 base.html 作为骨架

… 其他路由(如果需要)

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

重新运行应用。访问 http://127.0.0.1:5000。你应该看到留言板页面。填写姓名和留言,点击提交。页面会刷新,你的留言会显示在页面下方。

这里使用了 redirect(url_for('message_board'))。这是一个重要的Web开发模式,称为 POST/Redirect/GET (PRG)。它的目的是在成功处理 POST 请求后,不是直接渲染响应,而是向客户端发送一个重定向响应,告诉浏览器去访问另一个 URL(通常是同一个页面,但使用 GET 请求)。这样,当用户刷新页面时,浏览器会发送 GET 请求,而不是重复发送 POST 请求,从而避免重复提交表单数据。

9. 项目结构

随着你的应用变得越来越复杂,将所有代码放在一个 app.py 文件中会变得难以管理。一个良好的项目结构可以提高可读性和可维护性。

一种常见的 Flask 项目结构如下:

myflaskproject/
├── myflaskproject/ # Python 包目录 (你的应用代码)
│ ├── __init__.py # 应用工厂和配置
│ ├── routes.py # 视图函数和路由
│ ├── models.py # 数据库模型 (如果使用 ORM)
│ ├── forms.py # 表单定义 (如果使用 Flask-WTF 等扩展)
│ ├── static/ # 静态文件目录
│ │ ├── css/
│ │ └── js/
│ │ └── img/
│ └── templates/ # 模板文件目录
│ ├── base.html
│ ├── index.html
│ └── message_board.html
├── venv/ # 虚拟环境 (被忽略)
├── requirements.txt # 项目依赖列表
├── config.py # 应用配置文件
└── run.py # 启动脚本

在这种结构中:

  • myflaskproject/: 最外层的文件夹,包含整个项目。
  • myflaskproject/myflaskproject/: 内部的文件夹,这是一个 Python 包。你的所有应用代码都放在这里。
  • __init__.py: 通常包含一个应用工厂函数 (create_app()),用于创建 Flask 应用实例,加载配置,注册蓝图(稍后介绍)等。这使得应用的创建更加灵活,方便进行测试或创建应用的多个实例。
  • routes.py: 包含所有的视图函数和路由定义。
  • models.py: 如果你使用数据库和 ORM(如 Flask-SQLAlchemy),模型的定义会放在这里。
  • forms.py: 如果你使用表单处理库(如 Flask-WTF),表单类会定义在这里。
  • static/templates/: 保持原样,但它们现在位于内部的 myflaskproject 包中。
  • venv/: 虚拟环境文件夹,通常在版本控制中被忽略 (.gitignore)。
  • requirements.txt: 列出项目所有的 Python 依赖 (pip freeze > requirements.txt)。
  • config.py: 存放应用的配置信息,如数据库连接字符串、密钥等。
  • run.py: 一个简单的脚本,负责创建并运行应用实例。

示例 __init__.py:

“`python

myflaskproject/init.py

from flask import Flask

def create_app():
app = Flask(name)

# 可以加载配置
# app.config.from_object('config.Config')

# 注册路由
from . import routes # . 表示当前包
app.register_blueprint(routes.bp) # 蓝图稍后介绍,这里先假设用蓝图组织路由

# 可以初始化扩展
# db.init_app(app)

return app

“`

示例 routes.py:

“`python

myflaskproject/routes.py

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

创建一个蓝图

蓝图是一种组织路由的方式,可以将相关的路由和视图函数分组

bp = Blueprint(‘main’, name) # ‘main’ 是蓝图名称

简单的列表来存储留言(非持久化)

messages = []

@bp.route(‘/’, methods=[‘GET’, ‘POST’]) # 使用 bp.route 替代 app.route
def message_board():
if request.method == ‘POST’:
author = request.form.get(‘author’)
content = request.form.get(‘message’)
if author and content:
messages.append({‘author’: author, ‘content’: content})
return redirect(url_for(‘main.message_board’)) # 使用蓝图名.视图函数名
pass
return render_template(‘message_board.html’, messages=messages)

@bp.route(‘/about’)
def about():
return render_template(‘base.html’)
“`

示例 run.py:

“`python

run.py

from myflaskproject import create_app

app = create_app()

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

要运行这个结构的应用程序,在项目根目录(myflaskproject/ 所在的目录)激活虚拟环境,然后运行:

bash
python run.py

虽然对于入门来说,单文件应用足够简单直观,但理解这种模块化的项目结构对于构建更大型、更易于维护的应用至关重要。蓝图(Blueprint)是 Flask 组织应用的一种强大机制,允许你将应用分解成更小的、可重用的部分。

10. 下一步学习什么?

恭喜你!通过本文的学习,你已经掌握了 Flask Web 开发的基础知识。但这仅仅是一个开始。要构建更强大、更实用的 Web 应用,你还需要学习更多内容:

  • Flask 扩展 (Flask Extensions): 利用 Flask 社区提供的丰富扩展,例如:
    • Flask-SQLAlchemy: 集成 SQLAlchemy ORM,方便地进行数据库操作。
    • Flask-WTF: 简化表单的创建、处理和验证。
    • Flask-Login: 处理用户认证和会话管理。
    • Flask-Migrate: 数据库迁移工具 (基于 Alembic)。
    • Flask-RESTful / Flask-RESTX: 快速构建 RESTful APIs。
    • 还有很多其他扩展用于邮件发送、缓存、安全等等。
  • 数据库: 学习如何连接和使用数据库来持久化存储数据。常见的选择有 SQLite (适合小型应用或开发测试)、PostgreSQL、MySQL 等。
  • ORM (Object-Relational Mapping): 使用 SQLAlchemy 或 Flask-SQLAlchemy 等 ORM 工具,可以用 Python 对象的方式操作数据库,而不是直接写 SQL 语句。
  • 用户认证和授权: 学习如何实现用户注册、登录、会话管理、角色和权限控制。
  • 错误处理: 定义自定义错误页面(如 404 Not Found, 500 Internal Server Error)。
  • 上下文 (Contexts): 了解请求上下文 (Request Context) 和应用上下文 (App Context),以及它们在 Flask 中的作用。
  • 测试: 学习如何编写单元测试和集成测试来确保你的应用按预期工作。
  • 部署: 学习如何将你的 Flask 应用部署到生产环境的 Web 服务器上,如 Gunicorn, uWSGI 配合 Nginx 或 Apache,或者部署到云平台(如 Heroku, AWS, Azure, Google Cloud, Vercel)。
  • 微服务或大型应用结构: 了解更复杂的应用组织方式,如使用蓝图构建模块化应用,或者将应用分解为多个微服务。

11. 总结

Flask 是一个优雅、轻量级且高度灵活的 Python Web 框架。通过本文的学习,你已经了解了如何搭建环境、创建第一个应用、理解核心概念(路由、视图、请求/响应)、使用 Jinja2 模板以及处理静态文件和表单。

这为你打开了 Web 开发的大门。接下来的旅程将涉及更深入的数据库操作、用户管理、API 设计等。不断实践、查阅官方文档、探索 Flask 扩展,你将能够使用 Flask 构建出功能丰富、健壮的 Web 应用。

记住,最好的学习方式是动手实践。尝试修改本文中的示例代码,构建自己的小项目,解决遇到的问题。

祝你在 Flask 的世界里探索愉快!

发表评论

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

滚动至顶部