在 VS Code 中试用

Visual Studio Code 中的 Flask 教程

Flask 是一个轻量级的 Python Web 应用程序框架,提供了 URL 路由和页面呈现的基础功能。

Flask 被称为“微”框架,因为它不直接提供表单验证、数据库抽象、身份验证等功能。这些功能由称为 Flask 扩展的特殊 Python 包提供。这些扩展与 Flask 无缝集成,看起来就像是 Flask 本身的一部分。例如,Flask 不提供页面模板引擎,但安装 Flask 时默认包含 Jinja 模板引擎。为方便起见,我们通常将这些默认功能视为 Flask 的一部分。

在本 Flask 教程中,您将创建一个简单的 Flask 应用,该应用包含三个使用通用基础模板的页面。在此过程中,您将体验 Visual Studio Code 的多项功能,包括使用终端、编辑器、调试器、代码片段等。

此 Flask 教程的完整代码项目可在 GitHub 上找到:python-sample-vscode-flask-tutorial

如果您遇到任何问题,可以在 Python 扩展讨论问答 中搜索答案或提问。

先决条件

要成功完成本 Flask 教程,您必须执行以下操作(这些步骤与 通用 Python 教程 中的步骤相同)

  1. 安装 Python 扩展

  2. 安装 Python 3 的一个版本(本教程即以此版本编写)。选项包括

    • (所有操作系统)从 python.org 下载;通常使用页面上最先出现的“下载”按钮。
    • (Linux)内置的 Python 3 安装效果很好,但要安装其他 Python 包,必须在终端中运行 sudo apt install python3-pip
    • (macOS)使用 brew install python3 通过 Homebrew 在 macOS 上安装。
    • (所有操作系统)从 Anaconda 下载(用于数据科学目的)。
  3. 在 Windows 上,确保您的 Python 解释器位置包含在 PATH 环境变量中。您可以在命令提示符下运行 path 来检查位置。如果未包含 Python 解释器的文件夹,请打开 Windows 设置,搜索“环境”,选择“编辑帐户的环境变量”,然后编辑“Path”变量以包含该文件夹。

为 Flask 教程创建项目环境

在本节中,您将创建一个安装了 Flask 的虚拟环境。使用虚拟环境可以避免将 Flask 安装到全局 Python 环境中,并让您对应用程序中使用的库进行精确控制。

  1. 在文件系统中,为本教程创建一个文件夹,例如 hello_flask

  2. 在终端中导航到该文件夹并运行 code .,或运行 VS Code 并使用“文件”>“打开文件夹”命令,在 VS Code 中打开此文件夹。

  3. 在 VS Code 中,打开命令面板(“视图”>“命令面板”或(⇧⌘P (Windows, Linux Ctrl+Shift+P)))。然后选择“Python: 创建环境”命令,在工作区中创建一个虚拟环境。选择 venv,然后选择要用于创建环境的 Python 环境。

    注意:如果您想手动创建环境,或在环境创建过程中遇到错误,请访问环境页面。

    Flask tutorial: opening the Command Palette in VS Code

  4. 虚拟环境创建完成后,从命令面板运行终端: 创建新终端⌃⇧` (Windows, Linux Ctrl+Shift+`))),这将创建一个终端并通过运行其激活脚本自动激活虚拟环境。

    注意:在 Windows 上,如果您的默认终端类型是 PowerShell,您可能会看到一个错误,提示无法运行 activate.ps1,因为系统禁用了脚本运行。该错误提供了一个链接,其中包含有关如何允许脚本的信息。否则,使用“终端: 选择默认配置文件”将“命令提示符”或“Git Bash”设置为您的默认配置文件。

  5. 在 VS Code 终端中运行以下命令,在虚拟环境中安装 Flask

    python -m pip install flask
    

您现在已拥有一个独立的 Flask 代码编写环境。当您使用“终端: 创建新终端”时,VS Code 会自动激活该环境。如果您打开单独的命令提示符或终端,请通过运行 source .venv/bin/activate (Linux/macOS) 或 .venv\Scripts\Activate.ps1 (Windows) 来激活环境。当命令提示符开头显示 (.venv) 时,您就知道环境已激活。

创建并运行一个最小的 Flask 应用

  1. 在 VS Code 中,使用菜单中的“文件”>“新建”、按 Ctrl+N,或使用资源管理器视图中的新建文件图标(如下所示),在项目文件夹中创建一个名为 app.py 的新文件。

    Flask tutorial: new file icon in Explorer View

  2. app.py 中,添加代码以导入 Flask 并创建一个 Flask 对象实例。如果您键入下面的代码(而不是复制粘贴),您可以观察到 VS Code 的智能感知和自动补全功能

    from flask import Flask
    app = Flask(__name__)
    
  3. 同样在 app.py 中,添加一个返回内容的函数(在本例中是一个简单字符串),并使用 Flask 的 app.route 装饰器将 URL 路由 / 映射到该函数

    @app.route("/")
    def home():
        return "Hello, Flask!"
    

    提示:您可以在同一个函数上使用多个装饰器,每行一个,具体取决于您要映射到同一个函数的不同路由数量。

  4. 保存 app.py 文件(⌘S (Windows, Linux Ctrl+S))。

  5. 在集成终端中,输入 python -m flask run 运行应用,这将运行 Flask 开发服务器。开发服务器默认查找 app.py。运行 Flask 时,您应该看到类似如下的输出

    (.venv) D:\py\\hello_flask>python -m flask run
     * Environment: production
       WARNING: Do not use the development server in a production environment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    

    如果您看到找不到 Flask 模块的错误,请确保您已在虚拟环境中运行了 python -m pip install flask,如上一节末尾所述。

    此外,如果您想在不同的 IP 地址或端口上运行开发服务器,请使用 host 和 port 命令行参数,例如 --host=0.0.0.0 --port=80

  6. 要使用默认浏览器打开呈现的页面,请Ctrl+单击终端中的 URL http://127.0.0.1:5000/

    Flask tutorial: the running app in a browser

  7. 请注意,当您访问诸如 / 的 URL 时,调试终端中会出现一条消息,显示 HTTP 请求

    127.0.0.1 - - [11/Jul/2018 08:40:15] "GET / HTTP/1.1" 200 -
    
  8. 在终端中使用Ctrl+C停止应用。

提示:当使用不同于 app.py 的文件名时(例如 webapp.py),您需要定义一个名为 FLASK_APP 的环境变量并将其值设置为您选择的文件。然后 Flask 的开发服务器将使用 FLASK_APP 的值而不是默认文件 app.py。有关更多信息,请参阅Flask 命令行界面

在调试器中运行应用

调试让您有机会在特定代码行暂停正在运行的程序。程序暂停时,您可以检查变量、在调试控制台面板中运行代码,以及利用调试页面上描述的其他功能。运行调试器还会在调试会话开始前自动保存所有修改过的文件。

开始之前:请确保您已在上一节末尾使用终端中的Ctrl+C停止了正在运行的应用。如果在一个终端中让应用保持运行,它会继续占用端口。因此,当您在调试器中使用同一端口运行应用时,原始正在运行的应用会处理所有请求,您将看不到正在调试的应用中的任何活动,并且程序不会在断点处停止。换句话说,如果调试器似乎不起作用,请确保没有其他应用实例仍在运行。

  1. app.py 的内容替换为以下代码,该代码添加了第二个路由和函数,您可以在调试器中逐行执行

    import re
    from datetime import datetime
    
    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.route("/")
    def home():
        return "Hello, Flask!"
    
    
    @app.route("/hello/<name>")
    def hello_there(name):
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        # Filter the name argument to letters only using regular expressions. URL arguments
        # can contain arbitrary text, so we restrict to safe characters only.
        match_object = re.match("[a-zA-Z]+", name)
    
        if match_object:
            clean_name = match_object.group(0)
        else:
            clean_name = "Friend"
    
        content = "Hello there, " + clean_name + "! It's " + formatted_now
        return content
    

    新 URL 路由 /hello/<name> 使用的装饰器定义了一个可以接受任何额外值的端点 /hello/。路由中 <> 内部的标识符定义了一个变量,该变量被传递给函数,并可在您的代码中使用。

    URL 路由区分大小写。例如,路由 /hello/<name>/Hello/<name> 不同。如果您希望同一个函数处理这两个路由,请为每个变体使用装饰器。

    如代码注释中所述,始终过滤任意用户提供的信息,以避免对应用进行各种攻击。在本例中,代码过滤 name 参数,使其只包含字母,从而避免注入控制字符、HTML 等。(当您在下一节中使用模板时,Flask 会进行自动过滤,您将不再需要此代码。)

  2. 通过以下任一方法,在 hello_there 函数的第一行代码 (now = datetime.now()) 处设置一个断点

    • 将光标置于该行,按 F9,或,
    • 将光标置于该行,选择“运行”>“切换断点”菜单命令,或,
    • 直接单击行号左侧的边距(将鼠标悬停在那里时会出现一个浅红色圆点)。

    断点在左侧边距显示为一个红色圆点

    Flask tutorial: a breakpoint set on the first line of the hello_there function

  3. 切换到 VS Code 中的“运行和调试”视图(使用左侧活动栏或(⇧⌘D (Windows, Linux Ctrl+Shift+D)))。您可能会看到消息“要自定义运行和调试,请创建 launch.json 文件”。这意味着您还没有包含调试配置的 launch.json 文件。如果单击“创建 launch.json 文件”链接,VS Code 可以为您创建该文件

    Flask tutorial: initial view of the debug panel

  4. 选择该链接,VS Code 将提示您选择调试配置。从下拉列表中选择“Flask”,VS Code 将使用 Flask 运行配置填充新的 launch.json 文件。launch.json 文件包含许多调试配置,每个配置都是 configuration 数组中的一个独立的 JSON 对象。

  5. 向下滚动并检查名为“Python: Flask”的配置。此配置包含 "module": "flask",,这告诉 VS Code 在启动调试器时使用 -m flask 运行 Python。它还在 env 属性中定义了 FLASK_APP 环境变量,以识别启动文件,默认是 app.py,但也允许您轻松指定不同的文件。如果您想更改 host 和/或 port,可以使用 args 数组。

    {
        "name": "Python Debugger: Flask",
        "type": "debugpy",
        "request": "launch",
        "module": "flask",
        "env": {
            "FLASK_APP": "app.py",
            "FLASK_DEBUG": "1"
        },
        "args": [
            "run",
            "--no-debugger",
            "--no-reload"
        ],
        "jinja": true,
        "justMyCode": true
    },
    

    注意:如果配置中的 env 条目包含 "FLASK_APP": "${workspaceFolder}/app.py",请将其更改为如上所示的 "FLASK_APP": "app.py"。否则,您可能会遇到错误消息,例如“无法导入模块 C”,其中 C 是项目文件夹所在的驱动器号。

    注意:创建 launch.json 后,编辑器中会出现一个“添加配置”按钮。该按钮显示一个列表,其中包含要添加到配置列表开头的其他配置。(“运行”>“添加配置”菜单命令执行相同的操作。)

  6. 保存 launch.json⌘S (Windows, Linux Ctrl+S))。在调试配置下拉列表中选择“Python: Flask”配置。

    Flask tutorial: selecting the Flask debugging configuration

  7. 通过选择“运行”>“启动调试”菜单命令或选择列表旁边的绿色“启动调试”箭头(F5)来启动调试器

    Flask tutorial: start debugging/continue arrow on the debug toolbar

    请注意,状态栏会改变颜色以指示正在调试

    Flask tutorial: appearance of the debugging status bar

    VS Code 中也会出现一个调试工具栏(如下所示),其中包含以下顺序的命令:暂停(或继续,F5)、跳过(F10)、进入(F11)、跳出(⇧F11 (Windows, Linux Shift+F11))、重启(⇧⌘F5 (Windows, Linux Ctrl+Shift+F5))和停止(⇧F5 (Windows, Linux Shift+F5))。有关每个命令的说明,请参阅VS Code 调试

    Flask tutorial: the VS Code debug toolbar

  8. 输出显示在“Python Debug Console”终端中。Ctrl+单击该终端中的链接 http://127.0.0.1:5000/ 以在浏览器中打开该 URL。在浏览器地址栏中,导航到 http://127.0.0.1:5000/hello/VSCode。在页面呈现之前,VS Code 会在您设置的断点处暂停程序。断点上的小黄色箭头表示它是下一行要运行的代码。

    Flask tutorial: VS Code paused at a breakpoint

  9. 使用“跳过”运行 now = datetime.now() 语句。

  10. 在 VS Code 窗口的左侧,您会看到一个“变量”窗格,其中显示局部变量(例如 now)以及参数(例如 name)。下面是“监视”、“调用堆栈”和“断点”窗格(有关详细信息,请参阅VS Code 调试)。在“局部变量”部分,尝试展开不同的值。您还可以双击值(或使用Enter (Windows, Linux F2))来修改它们。但是,更改诸如 now 之类的变量可能会中断程序。开发人员通常只在代码一开始未产生正确值时才进行更改以更正值。

    Flask tutorial: local variables and arguments in VS Code during debugging

  11. 程序暂停时,“调试控制台”面板(与终端面板中的“Python Debug Console”不同)允许您使用程序的当前状态试验表达式和尝试部分代码。例如,在您单步跳过 now = datetime.now() 行后,您可以试验不同的日期/时间格式。在编辑器中,选择代码 now.strftime("%A, %d %B, %Y at %X"),然后右键单击并选择“在调试控制台中评估”,将该代码发送到调试控制台,并在那里运行

    now.strftime("%A, %d %B, %Y at %X")
    'Wednesday, 31 October, 2018 at 18:13:39'
    

    提示:“调试控制台”还会显示应用内部可能不会出现在终端中的异常。例如,如果您在“运行和调试”视图的“调用堆栈”区域看到“在异常处暂停”消息,请切换到“调试控制台”查看异常消息。

  12. 将该行复制到调试控制台底部的 > 提示符中,然后尝试更改格式

    now.strftime("%a, %d %B, %Y at %X")
    'Wed, 31 October, 2018 at 18:13:39'
    now.strftime("%a, %d %b, %Y at %X")
    'Wed, 31 Oct, 2018 at 18:13:39'
    now.strftime("%a, %d %b, %y at %X")
    'Wed, 31 Oct, 18 at 18:13:39'
    
  13. 如果您愿意,可以单步执行更多行代码,然后选择“继续”(F5),让程序继续运行。浏览器窗口显示结果

    Flask tutorial: result of the modified program

  14. 更改代码中的行以使用不同的日期时间格式,例如 now.strftime("%a, %d %b, %y at %X"),然后保存文件。Flask 服务器将自动重新加载,这意味着更改将在无需重新启动调试器的情况下应用。刷新浏览器页面即可看到更新。

  15. 完成后,关闭浏览器并停止调试器。要停止调试器,请使用工具栏上的“停止”按钮(红色方块)或“运行”>“停止调试”命令(⇧F5 (Windows, Linux Shift+F5))。

提示:为了更容易地重复导航到特定的 URL,例如 http://127.0.0.1:5000/hello/VSCode,请使用 print 语句输出该 URL。该 URL 将显示在终端中,您可以使用Ctrl+单击在浏览器中打开它。

转到定义和查看定义命令

在使用 Flask 或任何其他库时,您可能想要检查这些库本身的代码。VS Code 提供了两个方便的命令,可以直接导航到任何代码中类和其他对象的定义处

  • 转到定义”从您的代码跳转到定义对象的代码处。例如,在 app.py 中,右键单击 Flask 类(在 app = Flask(__name__) 行中),然后选择“转到定义”(或使用F12),这将导航到 Flask 库中类的定义处。

  • 查看定义”(⌥F12 (Windows Alt+F12, Linux Ctrl+Shift+F10),也在右键上下文菜单中)与之类似,但直接在编辑器中显示类定义(在编辑器窗口中腾出空间以避免遮挡任何代码)。按Escape关闭查看窗口,或使用右上角的“x”。

    Flask tutorial: peek definition showing the Flask class inline

使用模板呈现页面

本教程中到目前为止创建的应用仅从 Python 代码生成纯文本网页。虽然可以直接在代码中生成 HTML,但开发人员会避免这种做法,因为它使应用容易受到跨站脚本 (XSS) 攻击。例如,在本教程的 hello_there 函数中,有人可能会想到用类似 content = "<h1>Hello there, " + clean_name + "!</h1>" 的代码来格式化输出,其中 content 中的结果直接提供给浏览器。这种开放性使得攻击者可以在 URL 中放置恶意 HTML(包括 JavaScript 代码),这些代码最终会进入 clean_name 并因此在浏览器中运行。

更好的做法是完全通过使用模板将 HTML 从代码中分离出来,这样您的代码就只关注数据值,而不关注呈现。

  • 模板是包含代码在运行时提供的值的占位符的 HTML 文件。模板引擎负责在呈现页面时进行替换。因此,代码只关注数据值,而模板只关注标记。
  • Flask 的默认模板引擎是Jinja,安装 Flask 时会自动安装它。此引擎提供灵活的选项,包括自动转义(以防止 XSS 攻击)和模板继承。通过继承,您可以定义一个包含通用标记的基础页面,然后在此基础上构建页面特定的添加内容。

在本节中,您将使用模板创建一个单页面。在接下来的章节中,您将配置应用以提供静态文件,然后为应用创建多个页面,每个页面都包含一个来自基础模板的导航栏。

  1. hello_flask 文件夹内,创建一个名为 templates 的文件夹,这是 Flask 默认查找模板的位置。

  2. templates 文件夹中,创建一个名为 hello_there.html 的文件,内容如下。此模板包含两个名为“name”和“date”的占位符,它们由花括号对 {{}} 分隔。如您所见,您还可以直接在模板中包含格式化代码

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>Hello, Flask</title>
        </head>
        <body>
            {%if name %}
                <strong>Hello there, {{ name }}!</strong> It's {{ date.strftime("%A, %d %B, %Y at %X") }}.
            {% else %}
                What's your name? Provide it after /hello/ in the URL.
            {% endif %}
        </body>
    </html>
    

    提示:Flask 开发人员通常使用flask-babel 扩展进行日期格式化,而不是 strftime,因为 flask-babel 会考虑区域设置和时区。

  3. app.py 中,在文件顶部附近导入 Flask 的 render_template 函数

    from flask import render_template
    
  4. 同样在 app.py 中,修改 hello_there 函数以使用 render_template 加载模板并应用指定的值(并添加一个路由以识别没有 name 的情况)。render_template 假定第一个参数是相对于 templates 文件夹的。通常,开发人员将模板命名与其使用它们的函数相同,但不必匹配名称,因为您始终在代码中引用确切的文件名。

    @app.route("/hello/")
    @app.route("/hello/<name>")
    def hello_there(name = None):
        return render_template(
            "hello_there.html",
            name=name,
            date=datetime.now()
        )
    

    您可以看到代码现在简单得多,只关注数据值,因为标记和格式化都包含在模板中。

  5. 启动程序(在调试器内部或外部,使用⌃F5 (Windows, Linux Ctrl+F5)),导航到 /hello/name URL,并观察结果。

  6. 还可以尝试使用类似 <a%20value%20that%20could%20be%20HTML> 的名称导航到 /hello/name URL,以查看 Flask 的自动转义功能。在浏览器中,“name”值显示为纯文本,而不是渲染为实际元素。

提供静态文件

静态文件有两种类型。第一类是样式表等文件,页面模板可以直接引用它们。这类文件可以存放在应用中的任何文件夹中,但通常放置在 static 文件夹内。

第二类是您希望在代码中处理的文件,例如当您想要实现一个返回静态文件的 API 端点时。为此,Flask 对象包含一个内置方法 send_static_file,该方法生成一个包含应用 static 文件夹中静态文件的响应。

以下部分演示了这两种类型的静态文件。

在模板中引用静态文件

  1. hello_flask 文件夹中,创建一个名为 static 的文件夹。

  2. static 文件夹内,创建一个名为 site.css 的文件,内容如下。输入此代码后,还可以观察 VS Code 为 CSS 文件提供的语法高亮功能,包括颜色预览

    .message {
        font-weight: 600;
        color: blue;
    }
    
  3. templates/hello_there.html 中,在 </head> 标签之前添加以下行,这将创建对样式表的引用。

    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" />
    

    此处使用的 Flask url_for 标签创建了文件的正确路径。由于它可以接受变量作为参数,因此如果需要,url_for 允许您通过编程方式控制生成的路径。

  4. 同样在 templates/hello_there.html 中,用以下标记替换 <body> 元素的内容,这些标记使用 message 样式而不是 <strong> 标签(如果您只使用不带 name 的 hello/ URL,也会显示消息)

    {%if name %}
        <span class="message">Hello there, {{ name }}!</span> It's {{ date.strftime("%A, %d %B, %Y at %X") }}.
    {% else %}
        <span class="message">What's your name? Provide it after /hello/ in the URL.</span>
    {% endif %}
    
  5. 运行应用,导航到 /hello/name URL,并观察消息以蓝色呈现。完成后停止应用。

从代码中提供静态文件

  1. static 文件夹中,创建一个名为 data.json 的 JSON 数据文件,内容如下(这些是无意义的样本数据)

    {
      "01": {
        "note": "This data is very simple because we're demonstrating only the mechanism."
      }
    }
    
  2. app.py 中,添加一个带有路由 /api/data 的函数,该函数使用 send_static_file 方法返回静态数据文件

    @app.route("/api/data")
    def get_data():
        return app.send_static_file("data.json")
    
  3. 运行应用并导航到 /api/data 终结点,以查看静态文件是否返回。完成后停止应用。

创建扩展基础模板的多个模板

由于大多数 Web 应用都有多个页面,并且这些页面通常共享许多公共元素,因此开发人员会将这些公共元素分离到基本页面模板中,然后其他页面模板可以继承该基本模板(这也称为模板继承)。

此外,由于你可能会创建许多扩展同一模板的页面,因此在 VS Code 中创建代码片段会很有帮助,通过该片段可以快速初始化新的页面模板。代码片段有助于避免繁琐且容易出错的复制粘贴操作。

以下各部分逐步讲解此过程的不同部分。

创建基本页面模板和样式

Flask 中的基本页面模板包含一组页面的所有共享部分,包括对 CSS 文件、脚本文件等的引用。基本模板还定义一个或多个由扩展基本模板的其他模板需要重写的 标签。块标签在基本模板和扩展模板中都通过 {% block <name> %}{% endblock %} 进行分隔。

以下步骤演示了如何创建基本模板。

  1. templates 文件夹中,创建名为 layout.html 的文件,其内容如下,该文件包含名为“title”和“content”的块。如你所见,标记定义了一个简单的导航栏结构,其中包含指向主页、关于和联系人页面的链接,这些页面将在后面的部分中创建。每个链接再次使用 Flask 的 url_for 标签在运行时为匹配的路由生成链接。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>{% block title %}{% endblock %}</title>
            <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" />
        </head>
    
        <body>
            <div class="navbar">
                <a href="{{ url_for('home') }}" class="navbar-brand">Home</a>
                <a href="{{ url_for('about') }}" class="navbar-item">About</a>
                <a href="{{ url_for('contact') }}" class="navbar-item">Contact</a>
            </div>
    
            <div class="body-content">
                {% block content %}
                {% endblock %}
                <hr/>
                <footer>
                    <p>&copy; 2018</p>
                </footer>
            </div>
        </body>
    </html>
    
  2. 在现有的“message”样式下方,将以下样式添加到 static/site.css 中,并保存文件。请注意,本演练不试图演示响应式设计;这些样式只是生成一个合理有趣的成果。

    .navbar {
        background-color: lightslategray;
        font-size: 1em;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
        color: white;
        padding: 8px 5px 8px 5px;
    }
    
    .navbar a {
        text-decoration: none;
        color: inherit;
    }
    
    .navbar-brand {
        font-size: 1.2em;
        font-weight: 600;
    }
    
    .navbar-item {
        font-variant: small-caps;
        margin-left: 30px;
    }
    
    .body-content {
        padding: 5px;
        font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    

此时可以运行应用,但由于尚未在任何地方使用基本模板且未更改任何代码文件,因此结果与上一步相同。完成剩余部分即可看到最终效果。

创建代码片段

由于下一节中创建的三个页面都扩展了 layout.html,因此创建一个 代码片段 来初始化新的模板文件并正确引用基本模板可以节省时间。代码片段提供来自单个源的一致代码段,这避免了在使用现有代码进行复制粘贴时可能出现的错误。

  1. 在 VS Code 中,选择 文件 > 首选项 > 配置用户代码片段

  2. 在显示的列表中,选择 html。如果之前创建过代码片段,则该选项可能会在列表的“现有代码片段”部分显示为“html.json”。

  3. VS Code 打开 html.json 后,在现有的花括号内添加以下条目(此处未显示的解释性注释描述了详细信息,例如 $0 行指示 VS Code 插入代码片段后光标的位置):

    "Flask Tutorial: template extending layout.html": {
        "prefix": "flextlayout",
        "body": [
            "{% extends \"layout.html\" %}",
            "{% block title %}",
            "$0",
            "{% endblock %}",
            "{% block content %}",
            "{% endblock %}"
        ],
    
        "description": "Boilerplate template that extends layout.html"
    },
    
  4. 保存 html.json 文件(⌘S(Windows、Linux Ctrl+S)。

  5. 现在,每当开始键入代码片段的前缀(例如 flext)时,VS Code 都会提供该代码片段作为自动完成选项,如下一节所示。还可以使用“插入代码片段”命令从菜单中选择代码片段。

有关代码片段的详细信息,请参阅 创建代码片段

使用代码片段添加页面

有了代码片段,可以快速为主页、关于和联系人页面创建模板。

  1. templates 文件夹中,创建名为 home.html 的新文件,然后开始键入 flext 以查看代码片段作为完成选项出现

    Flask tutorial: autocompletion for the flextlayout code snippet

    选择完成选项时,将出现代码片段的代码,光标位于代码片段的插入点

    Flask tutorial: insertion of the flextlayout code snippet

  2. 在“title”块的插入点写入 Home,并在“content”块中写入 <p>这是 Visual Studio Code Flask 教程的主页。</p>,然后保存文件。这些行是扩展页面模板中唯一不同的部分

  3. templates 文件夹中,创建 about.html,使用代码片段插入样板标记,分别在“title”和“content”块中插入 关于我们<p>这是 Visual Studio Code Flask 教程的关于页面。</p>,然后保存文件。

  4. 重复上一步,创建 templates/contact.html,在两个内容块中使用 联系我们<p>这是 Visual Studio Code Flask 教程的联系人页面。</p>

  5. app.py 中,为 /about//contact/ 路由添加函数,这些函数引用各自的页面模板。同时修改 home 函数以使用 home.html 模板。

    # Replace the existing home function with the one below
    @app.route("/")
    def home():
        return render_template("home.html")
    
    # New functions
    @app.route("/about/")
    def about():
        return render_template("about.html")
    
    @app.route("/contact/")
    def contact():
        return render_template("contact.html")
    

运行应用

将所有页面模板准备好后,保存 app.py,运行应用,然后打开浏览器查看结果。在页面之间导航,以验证页面模板是否正确扩展了基本模板。

Flask tutorial: app rendering a common nav bar from the base template

注意:如果未看到最新更改,可能需要对页面进行硬刷新以避免看到缓存的文件。

可选活动

以下部分介绍了在处理 Python 和 Visual Studio Code 时可能觉得有用的其他步骤。

为环境创建 requirements.txt 文件

通过源代码管理或其他方式共享应用代码时,复制虚拟环境中的所有文件没有意义,因为接收者始终可以自己重新创建环境。

因此,开发人员通常会从源代码管理中省略虚拟环境文件夹,而是使用 requirements.txt 文件描述应用的依赖项。

尽管可以手动创建文件,但也可以使用 pip freeze 命令根据激活环境中安装的精确库生成文件

  1. 使用“Python: Select Interpreter”命令选择所选环境后,运行“终端: 创建新终端”命令(⌃⇧`(Windows、Linux Ctrl+Shift+`))以在该环境已激活的情况下打开终端。

  2. 在终端中,运行 pip freeze > requirements.txt 以在项目文件夹中创建 requirements.txt 文件。

任何收到项目副本的人(或任何生成服务器)只需运行 pip install -r requirements.txt 命令即可在原始环境中重新安装包。(但接收者仍需要创建自己的虚拟环境。)

注意pip freeze 列出当前环境中安装的所有 Python 包,包括当前未使用的包。该命令还会列出具有精确版本号的包,将来可能需要将其转换为范围以获得更大的灵活性。有关详细信息,请参阅 pip 命令文档中的requirements 文件

重构项目以支持进一步开发

在整个 Flask 教程中,所有应用代码都包含在单个 app.py 文件中。为了进一步开发和分离关注点,将 app.py 的各个部分重构为单独的文件会很有帮助。

  1. 在项目文件夹中,为应用创建一个文件夹,例如 hello_app,以将其文件与 requirements.txt 等其他项目级别文件以及 VS Code 存储设置和调试配置文件所在的 .vscode 文件夹分开。

  2. statictemplates 文件夹移动到 hello_app 中,因为这些文件夹肯定包含应用代码。

  3. hello_app 文件夹中,创建一个名为 views.py 的文件,其中包含路由和视图函数

    from flask import Flask
    from flask import render_template
    from datetime import datetime
    from . import app
    
    @app.route("/")
    def home():
        return render_template("home.html")
    
    @app.route("/about/")
    def about():
        return render_template("about.html")
    
    @app.route("/contact/")
    def contact():
        return render_template("contact.html")
    
    @app.route("/hello/")
    @app.route("/hello/<name>")
    def hello_there(name = None):
        return render_template(
            "hello_there.html",
            name=name,
            date=datetime.now()
        )
    
    @app.route("/api/data")
    def get_data():
        return app.send_static_file("data.json")
    
  4. hello_app 文件夹中,创建一个文件 __init__.py,其内容如下

    import flask
    app = flask.Flask(__name__)
    
  5. hello_app 文件夹中,创建一个文件 webapp.py,其内容如下

    # Entry point for the application.
    from . import app    # For application discovery by the 'flask' command.
    from . import views  # For import side-effects of setting up routes.
    
  6. 打开调试配置文件 launch.json,并按如下所示更新 env 属性以指向启动对象

    "env": {
        "FLASK_APP": "hello_app.webapp"
    },
    
  7. 删除项目根目录中的原始 app.py 文件,因为其内容已移至其他应用文件中。

  8. 现在,项目结构应类似于以下内容

    Flask tutorial: modified project structure with separate files and folders for parts of the app

  9. 再次在调试器中运行应用以确保一切正常。若要在 VS Code 调试器外部运行应用,请在终端中使用以下步骤

    1. 设置 FLASK_APP 环境变量。在 Linux 和 macOS 上,使用 export set FLASK_APP=webapp;在 Windows 上,如果使用 PowerShell,使用 $env:FLASK_APP=webapp,如果使用命令提示符,使用 set FLASK_APP=webapp
    2. 导航到 hello_app 文件夹,然后使用 python -m flask run 启动程序。

使用 Docker 扩展为 Flask 应用创建容器

[Docker 扩展](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) 使在 Visual Studio Code 中构建、管理和部署容器化应用程序变得容易。如果想了解如何为本教程中开发的 Flask 应用创建 Python 容器,请参阅容器中的 Python 教程,该教程将指导你如何

  • 创建描述简单 Python 容器的 Dockerfile 文件。
  • 构建、运行和验证 Flask 应用的功能。
  • 调试在容器中运行的应用。

如果您遇到任何问题,可以在 Python 扩展讨论问答 中搜索答案或提问。

后续步骤

恭喜你完成本演练,了解如何在 Visual Studio Code 中使用 Flask!

本教程的完整代码项目可在 GitHub 上找到:python-sample-vscode-flask-tutorial

由于本教程仅涉及页面模板的皮毛,有关模板的详细信息,请参阅 Jinja2 文档模板设计者文档 包含模板语言的所有详细信息。你可能还想查看官方 Flask 教程以及 Flask 扩展的文档。

若要在生产网站上试用应用,请查看教程使用 Docker 容器将 Python 应用部署到 Azure 应用服务。Azure 还提供一个标准容器,即Linux 上的应用服务,可以从 VS Code 内部将 Web 应用部署到其中。

你可能还想查阅 VS Code 文档中与 Python 相关的以下文章