零基础 Flask 教程:快速上手 Web 开发 – wiki基地


零基础 Flask 教程:快速上手 Web 开发

引言:踏上 Web 开发的奇妙旅程

欢迎来到 Web 开发的世界!如果你对构建网站充满好奇,却不知从何开始,那么你来对地方了。本教程将以 Python 最流行、最易学的微框架 Flask 为切入点,带你一步步构建你的第一个 Web 应用。忘记那些复杂的概念,我们将从零开始,用最直观的方式,让你快速感受到 Web 开发的乐趣和成就感。

Python 语言以其简洁优雅和强大的生态系统,成为了 Web 开发领域的一颗璀璨明星。而 Flask,作为 Python 的一个微框架,以其轻量级、灵活性和易用性,深受开发者喜爱。它不会为你预设过多的规则,让你能够自由选择组件和技术栈,非常适合初学者入门和构建中小型项目。

在本教程中,你将学习到:

  • Python 环境的搭建与虚拟环境的使用。
  • Flask 应用的基本结构和运行方式。
  • 路由、视图函数和 URL 映射。
  • 使用 Jinja2 模板引擎渲染动态 HTML。
  • 处理静态文件(CSS、JavaScript、图片)。
  • 如何接收和处理用户提交的表单数据。
  • 使用 SQLite 数据库进行数据存储和读取。
  • 通过蓝图(Blueprint)组织大型应用。
  • 基本的错误处理和调试技巧。
  • 部署应用的一些初步概念。

准备好了吗?让我们一起征服 Web 开发的第一个里程碑!

第一章:准备就绪——你的开发环境

在开始编写代码之前,我们需要搭建一个干净、高效的开发环境。这就像盖房子前打地基,非常重要。

1.1 安装 Python

首先,你的电脑上需要安装 Python。建议安装 Python 3.7 或更高版本。

  • Windows 用户: 访问 Python 官方网站 (python.org) 下载最新版本的安装包。在安装过程中,务必勾选 “Add Python to PATH” 选项,这样你就可以在命令行中直接使用 python 命令了。
  • macOS 用户: macOS 通常预装了 Python,但可能是旧版本。建议通过 Homebrew 安装最新版本:
    bash
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    brew install python
  • Linux 用户: 大多数 Linux 发行版都预装了 Python。如果没有,可以使用包管理器安装,例如 Ubuntu/Debian:
    bash
    sudo apt update
    sudo apt install python3 python3-pip

安装完成后,打开你的终端(Windows 为 cmd 或 PowerShell,macOS/Linux 为 Terminal),输入以下命令验证安装:

“`bash
python –version

python3 –version
pip –version

pip3 –version
“`

如果能正确显示 Python 和 pip 的版本号,说明安装成功。

1.2 理解并使用虚拟环境 (Virtual Environment)

虚拟环境是 Python 开发中的一项最佳实践。想象一下,你同时开发多个项目,每个项目可能依赖不同版本的库(比如项目 A 需要 Flask 1.x,项目 B 需要 Flask 2.x)。如果不使用虚拟环境,这些库就会安装在全局环境中,导致版本冲突,让你的开发环境一团糟。

虚拟环境为每个项目创建了一个独立的、隔离的 Python 环境。项目 A 的依赖只安装在项目 A 的虚拟环境中,不会影响到项目 B。

Python 3.3 及更高版本内置了 venv 模块来创建虚拟环境。

步骤:

  1. 创建项目文件夹:
    bash
    mkdir my_flask_app
    cd my_flask_app
  2. 创建虚拟环境: 在项目根目录下执行以下命令。这会在 my_flask_app 文件夹中创建一个名为 venv 的子文件夹,里面包含了独立的 Python 解释器和 pip。
    bash
    python3 -m venv venv
    # 或者如果你只有 python 命令:
    python -m venv venv
  3. 激活虚拟环境: 这是最关键的一步。激活后,你的命令行提示符会显示虚拟环境的名称(通常是 (venv)),表示你当前的操作都在这个隔离环境中。
    • macOS / Linux:
      bash
      source venv/bin/activate
    • Windows (Command Prompt):
      bash
      venv\Scripts\activate
    • Windows (PowerShell):
      bash
      .\venv\Scripts\activate

      当你的终端提示符前出现 (venv) 字样时,表示虚拟环境已成功激活。
  4. 安装 Flask: 虚拟环境激活后,使用 pip 安装 Flask。
    bash
    pip install Flask

    Flask 及其依赖库将被安装到当前的虚拟环境中。
  5. 退出虚拟环境: 当你完成开发或需要切换到其他项目时,可以输入 deactivate 命令退出虚拟环境。
    bash
    deactivate

    (venv) 标记会消失。

1.3 选择你的代码编辑器/IDE

一个好的代码编辑器能大幅提升你的开发效率。以下是几个推荐:

  • Visual Studio Code (VS Code): 免费、强大、功能丰富,拥有海量的扩展,是目前最受欢迎的代码编辑器之一。强烈推荐安装 Python 扩展。
  • PyCharm Community Edition: 专门为 Python 开发设计的 IDE,功能非常强大,对初学者也很友好。
  • Sublime Text / Atom: 轻量级但功能强大的文本编辑器,通过插件可以扩展为优秀的开发工具。

本教程中的代码示例将适用于任何编辑器。

第二章:Flask 初体验——你的第一个 Web 应用

现在,我们已经准备好环境,可以开始编写我们的第一个 Flask 应用了!我们将从一个经典的 “Hello, Flask!” 开始。

2.1 创建你的第一个 Flask 应用

  1. 确保虚拟环境已激活 (如果未激活,请回到 1.2 节激活)。
  2. my_flask_app 文件夹下创建一个名为 app.py 的文件。
  3. 将以下代码复制并粘贴到 app.py 中:

    “`python

    app.py

    1. 从 flask 模块中导入 Flask 类

    from flask import Flask

    2. 创建一个 Flask 应用实例

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

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

    app = Flask(name)

    3. 定义路由(URL 规则)和视图函数

    @app.route(‘/’) 装饰器将 URL 路径 ‘/’ 与下面的函数关联起来。

    当用户访问应用的根 URL 时,这个函数就会被调用。

    @app.route(‘/’)
    def hello_flask():
    “””
    这个视图函数会在用户访问根 URL 时被执行,
    并返回一个简单的字符串作为响应。
    “””
    return ‘Hello, Flask! 这是我的第一个 Web 应用!’

    4. 运行应用

    这一段代码确保只有当直接运行 app.py 文件时,app.run() 才会被调用。

    如果 app.py 被作为模块导入到其他文件中,app.run() 则不会执行。

    if name == ‘main‘:
    # debug=True 开启调试模式。
    # 在调试模式下,当代码发生改变时,服务器会自动重启;
    # 并且在出现错误时,会在浏览器中显示详细的错误信息(方便调试)。
    # 在生产环境中,务必关闭调试模式。
    app.run(debug=True)
    “`

2.2 运行你的应用

保存 app.py 文件后,回到你的终端(确保虚拟环境已激活),在 my_flask_app 目录下执行以下命令:

bash
flask run

或者,你也可以直接运行 Python 文件:

bash
python app.py

如果你看到类似这样的输出:

* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Press CTRL+C to quit

恭喜你!你的 Flask 应用已经成功运行了!

现在,打开你的 Web 浏览器,访问 http://127.0.0.1:5000/ (或者点击终端中显示的链接)。你将会在浏览器中看到 Hello, Flask! 这是我的第一个 Web 应用! 这段文字。

2.3 理解核心概念

  • Flask 实例: app = Flask(__name__) 是创建 Flask 应用的入口。__name__ 参数帮助 Flask 找到项目资源。
  • 路由 (Route): @app.route('/') 是一个装饰器,它将 URL /hello_flask() 函数绑定。当浏览器请求 / 时,hello_flask() 就会被执行。
  • 视图函数 (View Function): def hello_flask(): 就是一个视图函数。它的返回值(通常是字符串、HTML 或其他响应对象)会被发送回用户的浏览器。
  • app.run(debug=True) 启动内置的开发服务器。debug=True 开启了调试模式,这在开发阶段非常有用,它可以自动重载代码并提供详细的错误信息。

第三章:渲染动态内容——模板引擎 Jinja2

到目前为止,我们只返回了纯文本。但现代 Web 应用需要渲染复杂的 HTML 页面,并且这些页面的内容往往是动态变化的。这时,就需要使用模板引擎了。Flask 默认集成了强大的 Jinja2 模板引擎。

3.1 创建模板文件

  1. my_flask_app 目录下,创建一个名为 templates 的新文件夹。这是 Flask 查找模板文件的约定路径。
  2. templates 文件夹内,创建一个名为 index.html 的文件,并添加以下内容:

    “`html

    <!DOCTYPE html>




    我的 Flask 网站 – 首页

    欢迎,{{ user_name }}!

    这是一个使用 Flask 和 Jinja2 模板引擎渲染的动态页面。

    今天的天气是:{{ weather_info }}

    {% if user_name == "访客" %}
    <p>看起来你还没登录。欢迎注册或登录!</p>
    {% else %}
    <p>很高兴再次见到你,{{ user_name }}!</p>
    {% endif %}
    
    <h2>商品列表</h2>
    <ul>
        {% for item in products %}
            <li>{{ item.name }} - ¥{{ item.price }}</li>
        {% else %}
            <li>暂无商品。</li>
        {% endfor %}
    </ul>
    



    “`

3.2 在 Flask 中使用模板

修改 app.py,使其使用 render_template 函数来渲染 index.html

“`python

app.py

from flask import Flask, render_template # 导入 render_template 函数

app = Flask(name)

@app.route(‘/’)
def index():
“””
这个视图函数现在会渲染一个 HTML 模板,
并向模板传递动态数据。
“””
# 模拟一些动态数据
current_user = “Alice”
weather = “晴朗”
items = [
{“name”: “Python 入门书”, “price”: 99.00},
{“name”: “Flask 开发板”, “price”: 299.00},
{“name”: “Webcam”, “price”: 150.00},
]

# render_template('index.html', ...) 会查找 templates 文件夹下的 index.html
# 并将后面的关键字参数作为变量传递给模板。
return render_template('index.html',
                       user_name=current_user,
                       weather_info=weather,
                       products=items)

新增一个路由,演示条件判断

@app.route(‘/guest’)
def guest_page():
return render_template(‘index.html’,
user_name=”访客”, # 此时 user_name 为 “访客”
weather_info=”多云”,
products=[]) # 此时 products 为空列表

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

保存 app.py 后,如果你的应用还在运行(因为 debug=True),它会自动重启。刷新浏览器访问 http://127.0.0.1:5000/,你将看到一个带有动态内容的 HTML 页面。访问 http://127.0.0.1:5000/guest 则会看到访客页面。

3.3 Jinja2 模板语法简介

  • 变量: {{ variable_name }}。用双大括号包裹的变量会被 Flask 传递过来的实际值替换。
  • 控制结构: {% ... %}。用于实现逻辑,如 if/else 语句和 for 循环。
    • {% if condition %} / {% else %} / {% endif %}
    • {% for item in list %} / {% else %} / {% endfor %}
  • 注释: {# this is a comment #}。不会渲染到最终 HTML 中。

3.4 模板继承 (Template Inheritance)

在大型项目中,每个页面都会有共同的头部、底部、导航栏等。如果每个页面都复制粘贴这些内容,不仅效率低下,而且难以维护。模板继承机制解决了这个问题。

  1. templates 文件夹中创建 base.html 文件:

    html
    <!-- templates/base.html -->
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}我的 Flask 应用{% endblock %}</title>
    <!-- 引入静态 CSS 文件,我们稍后会讲到 -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
    </head>
    <body>
    <nav>
    <a href="/">首页</a> |
    <a href="/about">关于我们</a> |
    <a href="/contact">联系我们</a>
    </nav>
    <hr>
    <div class="content">
    {% block content %}
    <!-- 子模板将在这里插入其内容 -->
    {% endblock %}
    </div>
    <hr>
    <footer>
    <p>&copy; 2023 我的 Flask 应用. All rights reserved.</p>
    </footer>
    </body>
    </html>

  2. 修改 index.html 和其他页面,使其继承 base.html

    “`html

    {% extends “base.html” %} {# 声明继承 base.html #}

    {% block title %}首页 – 我的 Flask 网站{% endblock %} {# 覆盖 base.html 中的 title 块 #}

    {% block content %} {# 在 content 块中写入页面特有的内容 #}

    欢迎,{{ user_name }}!

    这是一个使用 Flask 和 Jinja2 模板引擎渲染的动态页面。

    今天的天气是:{{ weather_info }}

    {% if user_name == "访客" %}
    <p>看起来你还没登录。欢迎注册或登录!</p>
    {% else %}
    <p>很高兴再次见到你,{{ user_name }}!</p>
    {% endif %}
    
    <h2>商品列表</h2>
    <ul>
        {% for item in products %}
            <li>{{ item.name }} - ¥{{ item.price }}</li>
        {% else %}
            <li>暂无商品。</li>
        {% endfor %}
    </ul>
    

    {% endblock %}
    “`

    现在,创建新的页面比如 about.htmlcontact.html 将会非常简单:

    “`html

    {% extends “base.html” %}

    {% block title %}关于我们 – 我的 Flask 网站{% endblock %}

    {% block content %}

    关于我们

    我们致力于使用 Flask 框架构建高效、优雅的 Web 应用。

    我们是 Web 开发的热爱者和探索者。

    {% endblock %}
    “`

  3. app.py 中添加路由:

    “`python

    app.py (继续在原有代码上添加)

    … (前面的代码) …

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

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

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

    “`

重启应用,访问 /about/contact,你会看到它们都共享了 base.html 的结构,但内容是独特的。

第四章:静态文件与资源

Web 应用不仅仅只有 HTML,还需要 CSS 来美化页面,JavaScript 来增加交互,以及图片等多媒体资源。这些文件被称为静态文件。

Flask 约定将静态文件存放在项目根目录下的 static 文件夹中。

  1. my_flask_app 目录下创建 static 文件夹。
  2. static 文件夹下,再创建一个 css 文件夹。
  3. css 文件夹内,创建 style.css 文件,并添加一些简单的样式:

    css
    /* static/css/style.css */
    body {
    font-family: Arial, sans-serif;
    line-height: 1.6;
    margin: 0;
    padding: 20px;
    background-color: #f4f4f4;
    color: #333;
    }
    h1, h2 {
    color: #0056b3;
    }
    nav {
    background: #333;
    color: #fff;
    padding: 10px 0;
    text-align: center;
    }
    nav a {
    color: #fff;
    text-decoration: none;
    padding: 0 15px;
    }
    nav a:hover {
    text-decoration: underline;
    }
    .content {
    background: #fff;
    padding: 20px;
    margin: 20px 0;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    footer {
    text-align: center;
    padding: 20px;
    margin-top: 20px;
    color: #777;
    border-top: 1px solid #ccc;
    }

  4. base.html 中,我们已经使用了 {{ url_for('static', filename='css/style.css') }} 来链接这个 CSS 文件。url_for() 是 Flask 提供的一个非常实用的函数,它可以根据视图函数或静态文件的名称动态生成 URL,避免了硬编码路径的问题,让你的应用更具可维护性和健壮性。

刷新浏览器,你的页面现在应该变得漂亮多了!同样,你也可以在 static 文件夹下创建 js 文件夹来存放 JavaScript 文件,或 img 文件夹来存放图片,并使用 url_for('static', filename='js/script.js')url_for('static', filename='img/logo.png') 来引用它们。

第五章:处理用户输入——表单与请求

Web 应用的核心是用户交互。用户通过表单提交数据,服务器接收并处理这些数据。

5.1 HTTP 方法:GET 与 POST

  • GET: 通常用于从服务器请求数据。提交的数据会附加在 URL 的查询字符串中(如 example.com/search?query=flask)。数据量有限,不适合传输敏感信息。
  • POST: 通常用于向服务器提交数据,例如表单提交、上传文件等。数据在 HTTP 请求体中传输,不会显示在 URL 中,数据量也更大,更适合传输敏感或大量数据。

5.2 构建一个简单的表单

修改 app.pyindex.html,添加一个简单的消息提交表单。

  1. 修改 index.html (在 {% block content %} 块内添加):

    html
    {# templates/index.html (在商品列表下方添加) #}
    ...
    <h2>留言板</h2>
    <form action="/submit_message" method="post">
    <p>
    <label for="username">你的名字:</label><br>
    <input type="text" id="username" name="username" required>
    </p>
    <p>
    <label for="message">留言内容:</label><br>
    <textarea id="message" name="message" rows="5" required></textarea>
    </p>
    <p>
    <input type="submit" value="提交留言">
    </p>
    </form>
    ...

  2. 修改 app.py,导入 requestredirecturl_for,并添加处理表单的路由:

    “`python

    app.py

    from flask import Flask, render_template, request, redirect, url_for, flash, get_flashed_messages # 新增 request, redirect, url_for, flash, get_flashed_messages

    app = Flask(name)
    app.secret_key = ‘your_super_secret_key_here’ # 用于闪现消息等会话管理,非常重要!

    … (前面的 index, guest, about, contact 路由) …

    @app.route(‘/submit_message’, methods=[‘GET’, ‘POST’])
    def submit_message():
    if request.method == ‘POST’:
    # 获取表单数据
    username = request.form[‘username’]
    message = request.form[‘message’]

        # 这里可以进行数据验证和存储(我们稍后会集成数据库)
        print(f"收到来自 {username} 的留言: {message}") # 暂时打印到控制台
    
        # 使用 flash 消息给用户反馈
        flash(f'感谢 {username} 的留言!', 'success') # 'success' 是类别,可以用于不同样式的消息
    
        # 重定向到首页,避免表单重复提交
        return redirect(url_for('index'))
    else:
        # 如果是 GET 请求,也可以渲染一个表单页面
        # 不过我们这里直接在首页显示表单,所以这里可以简单重定向或返回错误
        return redirect(url_for('index'))
    

    在所有需要显示闪现消息的模板中,你需要获取它们。

    我们可以在 base.html 中添加显示闪现消息的逻辑。

    先修改 index 路由,使其也能获取闪现消息

    @app.route(‘/’)
    def index():
    current_user = “Alice”
    weather = “晴朗”
    items = [
    {“name”: “Python 入门书”, “price”: 99.00},
    {“name”: “Flask 开发板”, “price”: 299.00},
    {“name”: “Webcam”, “price”: 150.00},
    ]
    # 获取所有闪现消息
    messages = get_flashed_messages(with_categories=True) # with_categories=True 会返回 (category, message) 元组

    return render_template('index.html',
                           user_name=current_user,
                           weather_info=weather,
                           products=items,
                           messages=messages) # 将消息传递给模板
    

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

    “`

  3. 修改 base.html,在 div.content 块的上方或内部添加显示闪现消息的代码:

    html
    {# templates/base.html (在 {% block content %} 块之前添加) #}
    ...
    <body>
    <nav>...</nav>
    <hr>
    <div class="messages">
    {% with messages = get_flashed_messages(with_categories=true) %}
    {% if messages %}
    {% for category, message in messages %}
    <div class="flash-{{ category }}">{{ message }}</div>
    {% endfor %}
    {% endif %}
    {% endwith %}
    </div>
    <div class="content">
    {% block content %}
    ...
    {% endblock %}
    </div>
    ...
    </body>

    注意:app.py 中,我们给 app 实例设置了一个 secret_key。这是 Flask 用来加密会话信息(包括 flash 消息)的密钥。在生产环境中,这必须是一个复杂且保密的值。

重启应用。在首页填写表单并提交,你将看到一条“感谢 XXX 的留言!”的闪现消息,并且页面会刷新。此时查看终端,你也会看到打印出来的留言信息。

5.3 request 对象详解

request 对象是 Flask 中一个非常重要的全局对象,它包含了当前请求的所有信息,例如:

  • request.method:请求方法(GET, POST, PUT, DELETE 等)。
  • request.form:一个字典,包含了 POST 请求中表单提交的数据。
  • request.args:一个字典,包含了 GET 请求中 URL 查询字符串的参数。
  • request.json:如果请求体是 JSON 格式,则解析后的 JSON 数据。
  • request.files:一个字典,包含了上传的文件。
  • request.cookies:一个字典,包含了请求中的 Cookie。
  • request.headers:一个字典,包含了请求的 HTTP 头。

第六章:数据持久化——轻量级数据库 SQLite

现在我们只能将留言打印到控制台,一旦应用重启,数据就丢失了。为了持久化存储数据,我们需要使用数据库。Flask 可以与各种数据库集成,从简单的 SQLite 到强大的 PostgreSQL 或 MySQL。对于小型应用和学习目的,SQLite 是一个非常方便的选择,因为它是一个无服务器的、文件化的数据库。

6.1 初始化数据库

我们需要一个脚本来创建数据库文件和表。

  1. my_flask_app 目录下创建一个名为 schema.sql 的文件:

    “`sql
    — schema.sql
    DROP TABLE IF EXISTS messages;

    CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL,
    message TEXT NOT NULL,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
    );
    “`

  2. my_flask_app 目录下创建一个名为 init_db.py 的文件,用于执行 schema.sql

    “`python

    init_db.py

    import sqlite3

    DATABASE = ‘database.db’ # 数据库文件名

    def init_db():
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()

    with open('schema.sql', 'r') as f:
        schema_script = f.read()
    
    cursor.executescript(schema_script) # 执行 SQL 脚本
    conn.commit()
    conn.close()
    print(f"数据库 {DATABASE} 初始化成功,messages 表已创建。")
    

    if name == ‘main‘:
    init_db()
    “`

  3. 在终端(确保虚拟环境激活)运行 init_db.py

    bash
    python init_db.py

    这会在你的 my_flask_app 目录下创建一个 database.db 文件,并创建 messages 表。

6.2 将数据存储到数据库

现在,我们将修改 app.py,使它能够将用户提交的留言存储到 database.db 中。

  1. app.py 中定义数据库连接函数:

    “`python

    app.py

    … (所有导入) …

    import sqlite3 # 导入 sqlite3 模块

    app = Flask(name)
    app.secret_key = ‘your_super_secret_key_here’ # 确保有密钥

    DATABASE = ‘database.db’ # 定义数据库文件名

    定义一个函数,用于获取数据库连接

    def get_db_connection():
    conn = sqlite3.connect(DATABASE)
    conn.row_factory = sqlite3.Row # 设置 row_factory,使查询结果可以像字典一样访问
    return conn

    … (所有路由) …

    @app.route(‘/’)
    def index():
    conn = get_db_connection()
    messages_db = conn.execute(‘SELECT username, message, timestamp FROM messages ORDER BY timestamp DESC’).fetchall()
    conn.close()

    current_user = "Alice"
    weather = "晴朗"
    items = [
        {"name": "Python 入门书", "price": 99.00},
        {"name": "Flask 开发板", "price": 299.00},
        {"name": "Webcam", "price": 150.00},
    ]
    messages_flash = get_flashed_messages(with_categories=True)
    
    return render_template('index.html',
                           user_name=current_user,
                           weather_info=weather,
                           products=items,
                           messages=messages_flash,
                           db_messages=messages_db) # 将数据库留言传递给模板
    

    @app.route(‘/submit_message’, methods=[‘GET’, ‘POST’])
    def submit_message():
    if request.method == ‘POST’:
    username = request.form[‘username’]
    message = request.form[‘message’]

        if not username or not message:
            flash('用户名和留言都不能为空!', 'error')
            return redirect(url_for('index'))
    
        # 连接数据库并插入数据
        conn = get_db_connection()
        conn.execute('INSERT INTO messages (username, message) VALUES (?, ?)',
                     (username, message))
        conn.commit()
        conn.close()
    
        flash(f'感谢 {username} 的留言!', 'success')
        return redirect(url_for('index'))
    else:
        return redirect(url_for('index'))
    

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

    “`

6.3 在模板中显示数据库数据

修改 index.html,在留言板表单下方添加显示历史留言的区域:

“`html
{# templates/index.html (在表单下方添加) #}

<h2>历史留言</h2>
{% if db_messages %}
    {% for msg in db_messages %}
        <div class="message-card">
            <strong>{{ msg.username }}</strong> 说:
            <p>{{ msg.message }}</p>
            <small>发布于:{{ msg.timestamp }}</small>
        </div>
        <hr>
    {% endfor %}
{% else %}
    <p>暂无留言。快来第一个留下你的足迹吧!</p>
{% endif %}

{% endblock %}
“`

同时,你可能需要在 static/css/style.css 中为 message-card 添加一些样式:

css
/* static/css/style.css */
/* ... (原有样式) ... */
.message-card {
background-color: #e9f5ff;
border: 1px solid #cce5ff;
border-radius: 5px;
padding: 10px 15px;
margin-bottom: 10px;
}
.message-card p {
margin: 5px 0;
}
.message-card small {
color: #666;
font-size: 0.8em;
}
.flash-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
padding: 10px;
margin-bottom: 15px;
border-radius: 5px;
}
.flash-error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
padding: 10px;
margin-bottom: 15px;
border-radius: 5px;
}

现在,重启你的 Flask 应用,提交留言后,刷新页面,你会发现留言已经被永久存储并显示出来了!

第七章:构建复杂应用——蓝图 (Blueprint)

随着应用的增长,所有的路由和视图函数都写在一个 app.py 文件中会变得非常混乱和难以管理。Flask 的蓝图机制提供了一种将应用划分为多个模块化组件的方法。每个蓝图都可以定义自己的路由、模板和静态文件。

想象一下,一个博客应用可能有“用户认证”模块、“文章管理”模块、“评论”模块。每个模块都可以是一个蓝图。

7.1 应用结构重构

我们将创建一个简单的认证蓝图来演示。

  1. my_flask_app 目录下创建 auth 文件夹。
  2. auth 文件夹内创建 __init__.py 文件 (使其成为一个 Python 包)。
  3. auth 文件夹内创建 views.py 文件,用于定义认证相关的路由。

auth/views.py:

“`python

auth/views.py

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

创建一个蓝图实例

‘auth’ 是蓝图的名称,name 是当前模块的名称

url_prefix=’/auth’ 会使所有此蓝图中定义的路由都以 /auth 开头

auth_bp = Blueprint(‘auth’, name, url_prefix=’/auth’)

@auth_bp.route(‘/login’, methods=[‘GET’, ‘POST’])
def login():
if request.method == ‘POST’:
username = request.form[‘username’]
password = request.form[‘password’]

    # 简单模拟登录逻辑
    if username == 'test' and password == 'password':
        flash('登录成功!', 'success')
        return redirect(url_for('index')) # 假设 index 是首页路由
    else:
        flash('用户名或密码错误。', 'error')
return render_template('auth/login.html')

@auth_bp.route(‘/register’, methods=[‘GET’, ‘POST’])
def register():
if request.method == ‘POST’:
username = request.form[‘username’]
password = request.form[‘password’]
# 简单模拟注册
if username and password:
flash(f’用户 {username} 注册成功!’, ‘success’)
return redirect(url_for(‘auth.login’)) # 重定向到登录页
else:
flash(‘用户名和密码不能为空。’, ‘error’)
return render_template(‘auth/register.html’)

@auth_bp.route(‘/logout’)
def logout():
flash(‘你已退出登录。’, ‘info’)
return redirect(url_for(‘index’))
“`

app.py (修改以注册蓝图):

“`python

app.py

… (所有导入,确保导入了 auth_bp) …

from auth.views import auth_bp # 从 auth.views 导入 auth_bp 蓝图

app = Flask(name)
app.secret_key = ‘your_super_secret_key_here’

… (get_db_connection, DATABASE 定义) …

注册蓝图

app.register_blueprint(auth_bp)

… (所有路由,包括 index, submit_message, about, contact) …

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

“`

7.2 创建蓝图的模板文件

templates 文件夹内创建 auth 文件夹,用于存放认证相关的模板:

templates/auth/login.html:

“`html

{% extends “base.html” %}

{% block title %}登录 – 我的 Flask 网站{% endblock %}

{% block content %}

用户登录



还没有账号?立即注册

{% endblock %}
“`

templates/auth/register.html:

“`html

{% extends “base.html” %}

{% block title %}注册 – 我的 Flask 网站{% endblock %}

{% block content %}

用户注册



已经有账号?立即登录

{% endblock %}
“`

最后,你可能想在 base.html 导航栏中添加登录/注册/退出链接:

“`html
{# templates/base.html (修改 nav 标签) #}


“`

重启应用,现在你可以访问 /auth/login/auth/register 了。蓝图使得管理大型应用变得更加有条理。注意 url_for('auth.login') 中的 'auth' 前缀,它指明了是哪个蓝图下的路由。

第八章:错误处理与调试

在开发过程中,错误是不可避免的。Flask 提供了灵活的错误处理机制和强大的调试工具。

8.1 调试模式 (Debug Mode)

在开发阶段,app.run(debug=True) 是你的好帮手。当代码出现错误时,它会在浏览器中显示一个交互式的调试器,你可以查看变量、执行代码,甚至回溯堆栈。

重要提示: 在生产环境中,debug=True 必须关闭!因为这会泄露敏感信息,存在安全风险。

8.2 自定义错误页面

除了调试模式,你还可以为特定的 HTTP 错误码(如 404 Not Found, 500 Internal Server Error)定义自定义的错误页面。

“`python

app.py (添加在所有路由的下方,if name 之前)

@app.errorhandler(404)
def page_not_found(error):
# 返回自定义的 404 页面
return render_template(‘404.html’), 404

可以为其他错误码添加处理

@app.errorhandler(500)

def internal_server_error(error):

return render_template(‘500.html’), 500

“`

创建 templates/404.html 文件:

“`html

{% extends “base.html” %}

{% block title %}页面未找到 – 404{% endblock %}

{% block content %}

404 – 页面未找到

抱歉,你访问的页面不存在。

回到首页

{% endblock %}
“`

现在,如果你访问一个不存在的 URL(例如 http://127.0.0.1:5000/nonexistent-page),你将看到你自定义的 404 错误页面。

第九章:部署初探——让世界看到你的应用

开发完成后,你需要将应用部署到服务器上,让其他人能够通过互联网访问。Flask 自带的开发服务器(app.run()) 仅适用于开发和测试,不适用于生产环境。生产环境需要使用更健壮、高性能的 WSGI 服务器,例如 Gunicorn、uWSGI。

部署的简要步骤 (概念性了解):

  1. 安装 WSGI 服务器:
    bash
    pip install gunicorn # 或 uwsgi
  2. 创建 requirements.txt 记录项目所有依赖。
    bash
    pip freeze > requirements.txt
  3. 配置 WSGI 服务器: 以 Gunicorn 为例,在项目根目录运行:
    bash
    gunicorn -w 4 app:app # -w 指定 worker 数量,app:app 指的是 app.py 文件中的 app 实例

    这会启动 Gunicorn 服务器,它将监听默认端口 8000。
  4. 使用 Nginx/Apache 作为反向代理: 在生产环境中,通常会在 WSGI 服务器前面放置一个 Nginx 或 Apache 服务器。它们处理静态文件、负载均衡、SSL 证书等,并将动态请求转发给 WSGI 服务器。
  5. 选择云平台: 将你的代码部署到云服务提供商(如 Heroku, Vercel, Railway, AWS EC2, Google Cloud, 阿里云等)。这些平台通常提供了简化的部署流程。

这是一个复杂的环节,初学者无需深入细节,但了解其概念是重要的。

第十章:提升与进阶——不止于此

本教程只是 Flask 开发的冰山一角。当你掌握了基础,可以进一步探索以下领域:

  • Flask 扩展: Flask 拥有丰富的扩展生态系统,它们可以帮助你快速添加复杂功能,例如:
    • Flask-WTF: 处理 Web 表单。
    • Flask-SQLAlchemy: 强大的 ORM (Object-Relational Mapping),简化数据库操作。
    • Flask-Login: 用户认证和会话管理。
    • Flask-Migrate: 数据库迁移工具。
    • Flask-Mail: 发送邮件。
  • 数据库: 学习更高级的数据库操作,使用 PostgreSQL 或 MySQL 等生产级数据库。
  • Web 安全: 学习如何防范常见的 Web 漏洞,如 CSRF、XSS、SQL 注入等。
  • 测试: 编写单元测试和集成测试,确保你的应用稳定可靠。
  • RESTful API: 使用 Flask 构建后端 API,为前端应用(如 React, Vue, Angular)提供数据服务。
  • 异步编程: 了解如何使用 async/await 处理高并发请求。
  • 持续集成/持续部署 (CI/CD): 自动化测试和部署流程。

结语:你的 Web 开发之旅才刚刚开始

恭喜你!你已经完成了这个零基础 Flask 教程,并成功构建了一个包含路由、模板、静态文件、表单处理和数据库存储的简单 Web 应用。这虽然只是一个起点,但你已经迈出了 Web 开发领域坚实的第一步。

Flask 的学习曲线非常平缓,它鼓励你理解每个部分的运作方式,而不是隐藏细节。这种透明度让你对整个 Web 应用的生命周期有了更深入的理解。

Web 开发是一个广阔而充满活力的领域。持续学习,不断尝试,将你天马行空的想法变为现实。祝你在未来的 Web 开发旅程中取得更大的成就!


学习资源推荐:

  • Flask 官方文档: https://flask.palletsprojects.com/ (最权威的资料)
  • The Flask Mega-Tutorial by Miguel Grinberg: 经典教程,涵盖 Flask 几乎所有方面。
  • Stack Overflow: 遇到问题时搜索答案的好地方。
  • GitHub: 学习开源项目,参与贡献。

现在,是时候将这些知识应用到你自己的项目中了!祝你好运!

发表评论

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

滚动至顶部