Visual Studio Code 中的 Django 教程
Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据操作的丰富支持。
在本 Django 教程中,您将创建一个简单的 Django 应用程序,其中包含三个使用通用基模板的页面。您将在 Visual Studio Code 的上下文中创建此应用程序,以便了解如何在 VS Code 终端、编辑器和调试器中使用 Django。本教程不会深入探讨 Django 本身的各种细节,例如使用数据模型和创建管理界面。有关这些方面的指南,请参阅本教程末尾提供的 Django 文档链接。
本 Django 教程中完成的代码项目可以在 GitHub 上找到:python-sample-vscode-django-tutorial。
如果您遇到任何问题,可以在 Python 扩展讨论问答 中搜索答案或提问。
先决条件
要成功完成本 Django 教程,您必须执行以下操作(与通用 Python 教程中的步骤相同)
-
安装Python 扩展。
-
安装 Python 3 版本(本教程为此版本编写)。选项包括
- (所有操作系统) 从 python.org 下载;通常使用页面上首先出现的下载 Python 3.9.1按钮(或任何最新版本)。
- (Linux) 内置的 Python 3 安装效果很好,但要安装其他 Python 包,您必须在终端中运行
sudo apt install python3-pip
。 - (macOS) 通过 Homebrew 在 macOS 上安装,使用
brew install python3
(macOS 上的系统安装的 Python 不受支持)。 - (所有操作系统) 从 Anaconda 下载(用于数据科学目的)。
-
在 Windows 上,请确保您的 Python 解释器的位置包含在您的 PATH 环境变量中。您可以在命令提示符下运行
path
来检查位置。如果 Python 解释器的文件夹未包含在内,请打开 Windows 设置,搜索“环境”,选择编辑您的帐户的环境变量,然后编辑Path变量以包含该文件夹。
为 Django 教程创建项目环境
在本节中,您将在其中安装 Django 的虚拟环境。使用虚拟环境可以避免将 Django 安装到全局 Python 环境中,并让您完全控制应用程序中使用的库。虚拟环境还可以轻松地为环境创建 requirements.txt 文件。
-
在您的文件系统中,为本教程创建一个项目文件夹,例如
hello_django
。 -
在该文件夹中,使用以下命令(根据您的计算机选择合适的命令)基于当前解释器创建一个名为
.venv
的虚拟环境# Linux sudo apt-get install python3-venv # If needed python3 -m venv .venv source .venv/bin/activate # macOS python3 -m venv .venv source .venv/bin/activate # Windows py -3 -m venv .venv .venv\scripts\activate
注意:在运行上述命令时,请使用标准 Python 安装。如果您使用来自 Anaconda 安装的
python.exe
,您会看到一个错误,因为 ensurepip 模块不可用,并且环境将处于未完成状态。 -
通过运行
code .
或运行 VS Code 并使用文件>打开文件夹命令,在 VS Code 中打开项目文件夹。 -
在 VS Code 中,打开命令面板(查看>命令面板或 (⇧⌘P(Windows、Linux Ctrl+Shift+P)))。然后选择Python: 选择解释器命令
-
该命令将显示一个可供 VS Code 自动定位的可用解释器列表(您的列表会有所不同;如果您没有看到所需的解释器,请参阅配置 Python 环境)。从列表中,选择项目文件夹中以
./.venv
或.\.venv
开头的虚拟环境 -
运行终端: 创建新的终端 (⌃⇧`(Windows、Linux Ctrl+Shift+`)))从命令面板,这将创建一个终端并通过运行其激活脚本自动激活虚拟环境。
注意:在 Windows 上,如果您的默认终端类型是 PowerShell,您可能会看到一个错误,它无法运行 activate.ps1,因为系统上禁用了运行脚本。该错误提供了有关如何允许脚本的链接。否则,请使用终端: 选择默认配置文件将“命令提示符”或“Git Bash”设置为默认值。
-
选定的环境将显示在 VS Code 状态栏的右侧,并注意到('.venv': venv)指示器,它告诉您正在使用虚拟环境
-
通过在 VS Code 终端中运行以下命令,更新虚拟环境中的 pip
python -m pip install --upgrade pip
-
通过在 VS Code 终端中运行以下命令,在虚拟环境中安装 Django
python -m pip install django
你现在拥有一个用于编写 Django 代码的自包含环境。当使用 终端:新建终端 (⌃⇧` (Windows, Linux Ctrl+Shift+`)) 时,VS Code 会自动激活该环境。如果打开一个单独的命令提示符或终端,请运行 source .venv/bin/activate
(Linux/macOS)或 .venv\Scripts\Activate.ps1
(Windows)来激活环境。命令提示符开头显示 (.venv) 表示环境已激活。
创建并运行最小的 Django 应用程序
在 Django 术语中,“Django 项目”包含多个站点级配置文件,以及一个或多个你部署到 Web 主机上的“应用”,以创建完整的 Web 应用程序。一个 Django 项目可以包含多个应用,每个应用通常在项目中具有独立的功能,同一个应用也可以存在于多个 Django 项目中。应用本身只是一个遵循 Django 期望的特定约定的 Python 包。
因此,要创建一个最小的 Django 应用,首先需要创建一个 Django 项目作为应用的容器,然后创建应用本身。在这两种情况下,你都使用 Django 管理实用程序 django-admin
,它在安装 Django 包时会自动安装。
创建 Django 项目
-
在 VS Code 终端(你的虚拟环境已激活)中,运行以下命令:
django-admin startproject web_project .
该
startproject
命令假设(通过末尾的.
)当前文件夹是你的项目文件夹,并在其中创建以下内容:-
manage.py
:项目的 Django 命令行管理实用程序。你使用python manage.py <command> [options]
运行项目的管理命令。 -
名为
web_project
的子文件夹,其中包含以下文件:__init__.py
:一个空文件,告诉 Python 该文件夹是一个 Python 包。asgi.py
:ASGI 兼容 Web 服务器用于服务你的项目的入口点。你通常保持该文件不变,因为它提供了生产 Web 服务器的挂钩。settings.py
:包含 Django 项目的设置,你将在开发 Web 应用过程中修改这些设置。urls.py
:包含 Django 项目的目录表,你也会在开发过程中修改它。wsgi.py
:WSGI 兼容 Web 服务器用于服务你的项目的入口点。你通常保持该文件不变,因为它提供了生产 Web 服务器的挂钩。
-
-
通过运行以下命令创建一个空的开发数据库:
python manage.py migrate
当你第一次运行服务器时,它会在
db.sqlite3
文件中创建一个默认的 SQLite 数据库,该数据库用于开发目的,但可以用于低流量的生产 Web 应用。有关数据库的更多信息,请参阅 数据库类型 部分。 -
要验证 Django 项目,请确保你的虚拟环境已激活,然后使用命令
python manage.py runserver
启动 Django 的开发服务器。服务器运行在默认端口 8000 上,你将在终端窗口中看到类似以下的输出:Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). June 13, 2023 - 18:38:07 Django version 4.2.2, using settings 'web_project.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.
Django 的内置 Web 服务器仅用于本地开发目的。但是,当你部署到 Web 主机时,Django 会使用主机的 Web 服务器。Django 项目中的
wsgi.py
和asgi.py
模块负责连接到生产服务器。如果你想使用与默认端口 8000 不同的端口,请在命令行中指定端口号,例如
python manage.py runserver 5000
。 -
Ctrl+点击 终端输出窗口中的
http://127.0.0.1:8000/
URL,在你的默认浏览器中打开该地址。如果 Django 安装正确且项目有效,你将看到以下所示的默认页面。VS Code 终端输出窗口也会显示服务器日志。 -
完成后,关闭浏览器窗口,并在 VS Code 中使用 Ctrl+C 停止服务器,如终端输出窗口所示。
创建 Django 应用
-
在 VS Code 终端(你的虚拟环境已激活)中,在你的项目文件夹(包含
manage.py
的地方)中运行管理实用程序的startapp
命令:python manage.py startapp hello
该命令会创建一个名为
hello
的文件夹,其中包含多个代码文件和一个子文件夹。其中,你经常会使用views.py
(包含定义 Web 应用中页面的函数)和models.py
(包含定义数据对象的类)。migrations
文件夹用于 Django 的管理实用程序来管理数据库版本,如本教程后面的内容所述。此外还有apps.py
(应用配置)、admin.py
(用于创建 管理界面)和tests.py
(用于 创建测试)文件,这些文件这里没有介绍。 -
修改
hello/views.py
,使其与以下代码匹配,该代码为应用的主页创建一个视图:from django.http import HttpResponse def home(request): return HttpResponse("Hello, Django!")
-
创建一个名为
hello/urls.py
的文件,并将其内容更改为以下内容。urls.py
文件是你在其中指定模式,将不同的 URL 路由到其相应的视图的地方。以下代码包含一个路由,将应用的根 URL (""
) 映射到刚刚添加到hello/views.py
的views.home
函数。from django.urls import path from hello import views urlpatterns = [ path("", views.home, name="home"), ]
-
web_project
文件夹还包含一个urls.py
文件,这是实际处理 URL 路由的地方。打开web_project/urls.py
并将其修改为以下代码(如果你愿意,可以保留说明性注释)。此代码使用django.urls.include
引入应用的hello/urls.py
,这将应用的路由保持在应用内部。当项目包含多个应用时,这种分离非常有用。from django.contrib import admin from django.urls import include, path urlpatterns = [ path("", include("hello.urls")), path('admin/', admin.site.urls) ]
-
保存所有修改后的文件。
-
在 VS Code 终端中,再次激活虚拟环境,使用
python manage.py runserver
运行开发服务器,并在浏览器中打开http://127.0.0.1:8000/
,你将看到一个呈现“Hello, Django”的页面。
创建调试器启动配置文件
你可能已经想知道,是否有一种更简单的方法来运行服务器和测试应用,而无需每次都键入 python manage.py runserver
。幸运的是,确实有!你可以在 VS Code 中创建一个自定义启动配置文件,该配置文件也用于不可避免的调试练习。
-
切换到 VS Code 中的 **运行** 视图(使用左侧的活动栏或 F5)。你可能会看到消息“要自定义运行和调试,请创建一个 launch.json 文件”。这意味着你还没有包含调试配置的
launch.json
文件。如果你点击 **创建 launch.json 文件** 链接,VS Code 可以为你创建它。 -
选择该链接,VS Code 会提示你选择一个调试配置。从下拉菜单中选择 **Django**,VS Code 会使用 Django 运行配置填充一个新的
launch.json
文件。launch.json
文件包含多个调试配置,每个配置都是configuration
数组中的一个单独的 JSON 对象。 -
向下滚动并检查名为“Python: Django”的配置。
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Python Debugger: Django", "type": "debugpy", "request": "launch", "program": "${workspaceFolder}\\manage.py", "args": ["runserver"], "django": true, "justMyCode": true } ] }
此配置告诉 VS Code 使用选定的 Python 解释器和
args
列表中的参数运行"${workspaceFolder}/manage.py"
。因此,使用此配置启动 VS Code 调试器与在 VS Code 终端中使用已激活的虚拟环境运行python manage.py runserver
相同。(如果你愿意,可以将端口号(例如"5000"
)添加到args
中。)"django": true
条目还告诉 VS Code 启用 Django 页面模板的调试,你将在本教程后面的内容中看到。 -
通过选择 **运行** > **启动调试** 菜单命令或选择列表旁边的绿色 **启动调试** 箭头 (F5) 来测试配置。
-
Ctrl+点击 终端输出窗口中的
http://127.0.0.1:8000/
URL,在浏览器中打开它,你会发现应用正在正常运行。 -
完成后,关闭浏览器并停止调试器。要停止调试器,请使用停止工具栏按钮(红色方块)或 **运行** > **停止调试** 命令 (⇧F5 (Windows, Linux Shift+F5))。
-
你现在可以在任何时候使用 **运行** > **启动调试** 来测试应用,这也有助于在调试会话开始之前自动保存所有修改后的文件。
探索调试器
调试使你能够在代码的特定行暂停正在运行的程序。当程序暂停时,你可以检查变量,在调试控制台面板中运行代码,以及利用 调试 中描述的其他功能。运行调试器还会在调试会话开始之前自动保存任何修改后的文件。
**在开始之前**:请确保在上一节结束时使用终端中的 Ctrl+C 停止了正在运行的应用。如果你在一个终端中让应用继续运行,它将继续拥有该端口。因此,当你使用相同端口在调试器中运行应用时,原始运行的应用将处理所有请求,你将不会在正在调试的应用中看到任何活动,并且程序不会在断点处停止。换句话说,如果调试器似乎没有正常工作,请确保没有其他应用实例仍在运行。
-
在
hello/urls.py
中,将一个路由添加到urlpatterns
列表中:path("hello/<name>", views.hello_there, name="hello_there"),
path
的第一个参数定义一个路由“hello/”,它接受一个名为 name 的变量字符串。该字符串将传递到path
的第二个参数中指定的views.hello_there
函数。URL 路由区分大小写。例如,路由
/hello/<name>
与/Hello/<name>
不同。如果你希望同一个视图函数处理两者,请为每个变体定义路径。 -
将
views.py
的内容替换为以下代码,以定义hello_there
函数,你可以在调试器中逐步执行该函数:import re from django.utils.timezone import datetime from django.http import HttpResponse def home(request): return HttpResponse("Hello, Django!") def hello_there(request, 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 HttpResponse(content)
URL 路由中定义的
name
变量作为参数传递给hello_there
函数。如代码注释中所述,始终过滤任意用户提供的信息,以避免各种对你的应用的攻击。在本例中,代码将name
参数过滤为仅包含字母,这将避免注入控制字符、HTML 等。(当你使用下一节中的模板时,Django 会自动进行过滤,你不需要这段代码。) -
通过执行以下任一操作,在
hello_there
函数(now = datetime.now()
)中的第一行代码处设置断点:- 将光标放在该行上,按 F9,或者,
- 将光标放在该行上,选择 **运行** > **切换断点** 菜单命令,或者,
- 直接点击行号左侧的边距(将鼠标悬停在该位置时会出现一个淡红色的圆点)。
断点将在左侧边距中显示为一个红点。
-
选择**运行** > **开始调试**菜单命令,或选择列表旁边的绿色**开始调试**箭头(F5)来启动调试器。
观察状态栏的颜色变化,表示正在进行调试。
VS Code 中还会出现一个调试工具栏(如下所示),其中包含以下顺序的命令:暂停(或继续,F5)、单步跳过(F10)、单步进入(F11)、单步跳出(⇧F11(Windows、Linux Shift+F11))、重启(⇧⌘F5(Windows、Linux Ctrl+Shift+F5))、停止(⇧F5(Windows、Linux Shift+F5))。有关每个命令的说明,请参阅VS Code 调试。
-
输出显示在“Python 调试控制台”终端中。打开浏览器并导航到
http://127.0.0.1:8000/hello/VSCode
。在页面呈现之前,VS Code 会在您设置的断点处暂停程序。断点上的小黄色箭头表示它是下一行要运行的代码。 -
使用单步跳过运行
now = datetime.now()
语句。 -
在 VS Code 窗口的左侧,您会看到一个**变量**窗格,其中显示局部变量(例如
now
)以及参数(例如name
)。在下方是**监视**、**调用堆栈**和**断点**窗格(有关详细信息,请参阅VS Code 调试)。在**局部变量**部分,尝试展开不同的值。您也可以双击值(或使用Enter(Windows、Linux F2))修改它们。但是,更改now
等变量可能会使程序崩溃。开发人员通常只在代码没有产生正确值时更改值,以更正它们。 -
当程序暂停时,**调试控制台**面板(与终端面板中的“Python 调试控制台”不同)允许您使用程序的当前状态来试验表达式并尝试代码片段。例如,在您单步跳过
now = datetime.now()
行后,您可能会尝试不同的日期/时间格式。在编辑器中,选择读取now.strftime("%A, %d %B, %Y at %X")
的代码,然后右键单击并选择**调试:求值**将该代码发送到调试控制台,在那里它会运行。now.strftime("%A, %d %B, %Y at %X") 'Friday, 07 September, 2018 at 07:46:32'
提示:**调试控制台**还显示应用程序内部的异常,这些异常可能不会出现在终端中。例如,如果您在**运行和调试**视图的**调用堆栈**区域看到“在异常处暂停”消息,请切换到**调试控制台**以查看异常消息。
-
将该行复制到调试控制台底部的>提示符中,并尝试更改格式。
now.strftime("%A, %d %B, %Y at %X") 'Tuesday, 13 June, 2023 at 18:03:19' now.strftime("%a, %d %b, %Y at %X") 'Tue, 13 Jun, 2023 at 18:03:19' now.strftime("%a, %d %b, %y at %X") 'Tue, 13 Jun, 23 at 18:03:19'
-
如果需要,单步执行几行代码,然后选择继续(F5)让程序运行。浏览器窗口显示结果。
-
更改代码中的行以使用不同的 datetime 格式,例如
now.strftime("%a, %d %b, %y at %X")
,然后保存文件。Django 服务器将自动重新加载,这意味着无需重新启动调试器即可应用更改。刷新浏览器上的页面以查看更新。 -
完成后,关闭浏览器并停止调试器。要停止调试器,请使用停止工具栏按钮(红色方块)或 **运行** > **停止调试** 命令 (⇧F5 (Windows, Linux Shift+F5))。
提示:为了更容易地重复导航到特定 URL(例如
http://127.0.0.1:8000/hello/VSCode
),请使用views.py
等文件中的某个位置输出该 URL。该 URL 将出现在 VS Code 终端中,您可以在其中使用Ctrl+单击在浏览器中打开它。
转到定义和窥视定义命令
在使用 Django 或任何其他库时,您可能希望检查这些库本身的代码。VS Code 提供两个方便的命令,可以直接导航到任何代码中类和其他对象的定义。
-
转到定义从您的代码跳转到定义对象的代码。例如,在
views.py
中,右键单击home
函数中的HttpResponse
,然后选择**转到定义**(或使用F12),这将导航到 Django 库中的类定义。 -
预览定义(⌥F12(Windows Alt+F12,Linux Ctrl+Shift+F10),也在右键单击上下文菜单中),类似,但直接在编辑器中显示类定义(在编辑器窗口中腾出空间以避免遮挡任何代码)。按Escape关闭预览窗口或使用右上角的x。
使用模板呈现页面
您在本教程中创建的应用程序到目前为止只从 Python 代码生成纯文本网页。虽然可以在代码中直接生成 HTML,但开发人员避免这种做法,因为它会使应用程序容易受到跨站点脚本 (XSS) 攻击的影响。例如,在本教程的hello_there
函数中,人们可能会认为在代码中使用类似content = "<h1>Hello there, " + clean_name + "!</h1>"
的内容来格式化输出,其中content
中的结果直接提供给浏览器。此漏洞允许攻击者在最终出现在clean_name
中的 URL 中放置恶意 HTML(包括 JavaScript 代码),从而最终在浏览器中运行。
一个更好的做法是完全将 HTML 保持在代码之外,使用模板,这样您的代码只关注数据值,而不关注渲染。
在 Django 中,模板是一个 HTML 文件,其中包含代码在运行时提供的值的占位符。然后,Django 模板引擎负责在渲染页面时进行替换,并提供自动转义以防止 XSS 攻击(也就是说,如果您尝试在数据值中使用 HTML,您只会看到以纯文本形式渲染的 HTML)。因此,代码只关心数据值,模板只关心标记。Django 模板提供了灵活的选项,例如模板继承,允许您定义一个包含常用标记的基页,然后在此基础上构建页面特定的添加内容。
在本节中,您首先使用模板创建单个页面。在后续部分,您将配置应用程序以提供静态文件,然后为应用程序创建多个页面,每个页面都包含来自基模板的导航栏。Django 模板还支持控制流和迭代,正如您在本教程后面的模板调试上下文中所见。
-
在
web_project/settings.py
文件中,找到INSTALLED_APPS
列表,并添加以下条目,这将确保项目了解该应用程序,以便它可以处理模板。'hello',
-
在
hello
文件夹中,创建一个名为templates
的文件夹,然后创建一个名为hello
的子文件夹以匹配应用程序名称(此两层文件夹结构是典型的 Django 约定)。 -
在
templates/hello
文件夹中,创建一个名为hello_there.html
的文件,其内容如下。此模板包含两个名为“name”和“date”的数据值的占位符,它们由一对花括号{{
和}}
分隔。所有其他不变文本都是模板的一部分,以及格式化标记(例如<strong>
)。如您所见,模板占位符还可以包含格式,管道|
符号后的表达式,在本例中使用 Django 的内置日期过滤器和时间过滤器。然后,代码只需要传递 datetime 的值,而不是预格式化的字符串。<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Hello, Django</title> </head> <body> <strong>Hello there, {{ name }}!</strong> It's {{ date | date:"l, d F, Y" }} at {{ date | time:"H:i:s" }} </body> </html>
-
在
views.py
的顶部,添加以下导入语句。from django.shortcuts import render
-
同样在
views.py
中,修改hello_there
函数以使用django.shortcuts.render
方法加载模板并提供模板上下文。上下文是在模板中使用的变量集。render
函数接受请求对象,然后是相对于templates
文件夹的模板路径,然后是上下文对象。(开发人员通常将模板命名为与其使用的函数相同,但匹配的名称不是必需的,因为您始终在代码中引用确切的文件名。)def hello_there(request, name): print(request.build_absolute_uri()) #optional return render( request, 'hello/hello_there.html', { 'name': name, 'date': datetime.now() } )
您可以看到,代码现在简单多了,只关注数据值,因为标记和格式都在模板中。
-
启动程序(在调试器内部或外部,使用⌃F5(Windows、Linux Ctrl+F5)),导航到/hello/name URL,并观察结果。
-
还可以尝试使用类似
<a%20value%20that%20could%20be%20HTML>
的名称导航到/hello/name URL,以查看 Django 的自动转义效果。在浏览器中,“name”值显示为纯文本,而不是呈现实际元素。
提供静态文件
静态文件是您的 Web 应用程序针对某些请求(例如 CSS 文件)按原样返回的内容。提供静态文件需要settings.py
中的INSTALLED_APPS
列表包含django.contrib.staticfiles
,该列表默认情况下包含在内。
在 Django 中提供静态文件是一门艺术,尤其是在部署到生产环境时。这里显示的是一种简单的办法,适用于 Django 开发服务器和 Gunicorn 等生产服务器。但是,对静态文件的完整处理超出了本教程的范围,因此有关更多信息,请参阅 Django 文档中的管理静态文件。
切换到生产环境时,导航到settings.py
,设置DEBUG=False
,并将ALLOWED_HOSTS = ['*']
更改为允许特定主机。这可能会在使用容器时导致更多工作。有关详细信息,请参阅问题 13。
为静态文件准备应用程序。
-
在项目
web_project/urls.py
中,添加以下import
语句。from django.contrib.staticfiles.urls import staticfiles_urlpatterns
-
在同一个文件中,在最后添加以下行,该行将标准静态文件 URL 包含到项目识别的列表中。
urlpatterns += staticfiles_urlpatterns()
在模板中引用静态文件。
-
在
hello
文件夹中,创建一个名为static
的文件夹。 -
在
static
文件夹中,创建一个名为hello
的子文件夹,匹配应用程序名称。创建额外的子文件夹的原因是,当您将 Django 项目部署到生产服务器时,您将所有静态文件收集到一个单独的文件夹中,然后由专用的静态文件服务器提供服务。
static/hello
子文件夹确保在收集应用程序的静态文件时,它们位于特定于应用程序的子文件夹中,并且不会与同一项目中其他应用程序的文件发生冲突。 -
在
static/hello
文件夹中,创建一个名为site.css
的文件,内容如下。输入此代码后,还要注意 VS Code 为 CSS 文件提供的语法高亮显示,包括颜色预览。.message { font-weight: 600; color: blue; }
-
在
templates/hello/hello_there.html
中,在<title>
元素之后添加以下行。{% load static %}
标签是一个自定义 Django 模板标签集,它允许您使用{% static %}
来引用像样式表这样的文件。{% load static %} <link rel="stylesheet" type="text/css" href="{% static 'hello/site.css' %}" />
-
同样在
templates/hello/hello_there.html
中,将<body>
元素的内容替换为以下使用message
样式而不是<strong>
标签的标记<span class="message">Hello, there {{ name }}!</span> It's {{ date | date:'l, d F, Y' }} at {{ date | time:'H:i:s' }}.
-
运行应用程序,导航到 /hello/name URL,并观察消息是否以蓝色呈现。完成后停止应用程序。
使用 collectstatic 命令
对于生产部署,您通常使用 python manage.py collectstatic
命令将所有应用程序的静态文件收集到一个单独的文件夹中。然后,您可以使用专用的静态文件服务器来提供这些文件,这通常会导致整体性能更好。以下步骤展示了如何进行此收集,尽管您在使用 Django 开发服务器运行时不会使用此收集。
-
在
web_project/settings.py
中,添加以下行,该行定义了一个使用collectstatic
命令时收集静态文件的位置STATIC_ROOT = BASE_DIR / 'static_collected'
-
在终端中,运行命令
python manage.py collectstatic
并观察hello/site.css
是否被复制到与manage.py
位于同一级别的static_collected
文件夹中。 -
实际上,在更改静态文件后和部署到生产环境之前,都要运行
collectstatic
。
创建扩展基模板的多个模板
由于大多数 Web 应用程序都有不止一个页面,而且这些页面通常共享许多共同元素,因此开发人员将这些共同元素分离到一个基本页面模板中,然后其他页面模板扩展该模板。(这也称为模板继承,意味着扩展的页面从基本页面继承元素。)
此外,由于您可能会创建许多扩展相同模板的页面,因此在 VS Code 中创建代码片段很有帮助,使用该代码片段您可以快速初始化新的页面模板。代码片段可以帮助您避免使用现有代码进行繁琐且容易出错的复制粘贴操作。
以下部分将逐步介绍此过程的不同部分。
创建基本页面模板和样式
Django 中的基本页面模板包含一组页面所有共享的部分,包括对 CSS 文件、脚本文件等的引用。基本模板还定义了一个或多个**块**标签,这些标签的内容将由扩展的模板覆盖。块标签由 {% block <name> %}
和 {% endblock %}
在基本模板和扩展模板中分隔。
以下步骤演示了如何创建基本模板。
-
在
templates/hello
文件夹中,创建一个名为layout.html
的文件,内容如下,其中包含名为“title”和“content”的块。如您所见,标记定义了一个简单的导航栏结构,其中包含指向主页、关于和联系页面的链接,您将在后面的部分中创建这些页面。请注意,使用 Django 的{% url %}
标签通过相应的 URL 模式的名称而不是通过相对路径来引用其他页面。<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>{% block title %}{% endblock %}</title> {% load static %} <link rel="stylesheet" type="text/css" href="{% static 'hello/site.css' %}"/> </head> <body> <div class="navbar"> <a href="{% url 'home' %}" class="navbar-brand">Home</a> <a href="{% url 'about' %}" class="navbar-item">About</a> <a href="{% url 'contact' %}" class="navbar-item">Contact</a> </div> <div class="body-content"> {% block content %} {% endblock %} <hr/> <footer> <p>© 2018</p> </footer> </div> </body> </html>
-
将以下样式添加到
static/hello/site.css
中现有“message”样式下方,然后保存文件。(本演练不试图演示响应式设计;这些样式只是生成一个相当有趣的成果。).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
,因此创建**代码片段**以使用适当的引用初始化基本模板的新模板文件,这可以节省时间。代码片段从单个源提供一致的代码块,这可以避免使用现有代码复制粘贴时可能出现的错误。
-
在 VS Code 中,选择**文件**(Windows/Linux)或**代码**(macOS)菜单,然后选择**首选项** > **用户代码片段**。
-
在出现的列表中,选择**html**。(如果您之前创建过代码片段,则该选项可能在列表的**现有代码片段**部分中显示为“html.json”。)
-
在 VS Code 打开
html.json
后,在现有的花括号内添加以下代码。(此处未显示的解释性注释描述了诸如$0
行如何指示 VS Code 在插入代码片段后放置光标的位置等详细信息。)"Django Tutorial: template extending layout.html": { "prefix": "djextlayout", "body": [ "{% extends \"hello/layout.html\" %}", "{% block title %}", "$0", "{% endblock %}", "{% block content %}", "{% endblock %}" ], "description": "Boilerplate template that extends layout.html" },
-
保存
html.json
文件 (⌘S (Windows、Linux Ctrl+S))。 -
现在,每当您开始键入代码片段的前缀(例如
djext
)时,VS Code 都会将代码片段提供为自动完成选项,如下一部分所示。您还可以使用**插入代码片段**命令从菜单中选择代码片段。
有关一般代码片段的更多信息,请参阅 创建代码片段。
使用代码片段添加页面
有了代码片段,您可以快速创建主页、关于和联系页面的模板。
-
在
templates/hello
文件夹中,创建一个名为home.html
的新文件。然后开始键入djext
以查看代码片段显示为完成选项。选择完成选项时,代码片段的代码将出现,光标位于代码片段的插入点。
-
在“title”块的插入点,写入
Home
,在“content”块中,写入<p>Home page for the Visual Studio Code Django tutorial.</p>
,然后保存文件。这些行是扩展页面模板中唯一的部分。 -
在
templates/hello
文件夹中,创建about.html
,使用代码片段插入样板标记,分别在“title”和“content”块中插入About us
和<p>About page for the Visual Studio Code Django tutorial.</p>
,然后保存文件。 -
重复上一步,使用
Contact us
和<p>Contact page for the Visual Studio Code Django tutorial.</p>
创建templates/hello/contact.html
。 -
在应用程序的
urls.py
中,添加 /about 和 /contact 页面的路由。请注意,path
函数的name
参数定义了您在模板中的{% url %}
标签中用来引用页面的名称。path("about/", views.about, name="about"), path("contact/", views.contact, name="contact"),
-
在
views.py
中,添加 /about 和 /contact 路由的函数,这些函数引用它们各自的页面模板。还要修改home
函数以使用home.html
模板。# Replace the existing home function with the one below def home(request): return render(request, "hello/home.html") def about(request): return render(request, "hello/about.html") def contact(request): return render(request, "hello/contact.html")
运行应用程序
所有页面模板都到位后,保存 views.py
,运行应用程序,并打开浏览器访问主页以查看结果。在页面之间导航以验证页面模板是否已正确扩展基本模板。
使用数据、数据模型和迁移
许多 Web 应用程序使用存储在数据库中的信息,Django 使得使用模型轻松地表示该数据库中的对象。在 Django 中,模型是一个从 django.db.models.Model
派生的 Python 类,它表示一个特定的数据库对象,通常是一个表。您将这些类放在应用程序的 models.py
文件中。
使用 Django 时,您几乎完全通过在代码中定义的模型来处理数据库。随着时间的推移,Django 的“迁移”将自动处理所有底层数据库的细节,因为您会随着时间的推移不断发展模型。一般工作流程如下所示
- 修改
models.py
文件中的模型。 - 运行
python manage.py makemigrations
以在migrations
文件夹中生成脚本,这些脚本将数据库从当前状态迁移到新状态。 - 运行
python manage.py migrate
以将脚本应用于实际数据库。
迁移脚本有效地记录了您对数据模型进行的所有增量更改。通过应用迁移,Django 会更新数据库以匹配您的模型。由于每个增量更改都有自己的脚本,因此 Django 可以自动将数据库的任何先前版本(包括新数据库)迁移到当前版本。因此,您只需要关心 models.py
中的模型,而无需关心底层数据库模式或迁移脚本。让 Django 处理这些部分!
同样,在代码中,您也完全使用模型类来存储和检索数据;Django 处理底层的细节。唯一的例外是,您可以使用 Django 管理工具 loaddata 命令 将数据写入数据库。此工具通常用于在 migrate
命令初始化模式后初始化数据集。
使用 db.sqlite3
文件时,您也可以使用 SQLite 浏览器 等工具直接处理数据库。使用此类工具添加或删除表中的记录是可以的,但避免对数据库模式进行更改,因为这样会导致数据库与应用程序的模型不同步。相反,请更改模型,运行 makemigrations
,然后运行 migrate
。
数据库类型
默认情况下,Django 为应用程序的数据库包含一个 db.sqlite3
文件,该文件适合开发工作。正如 何时使用 SQLite(sqlite.org)上所述,SQLite 适用于每天不超过 100K 次访问的中低流量站点,但并不推荐用于更高流量的站点。它还仅限于单台计算机,因此无法在任何多服务器场景(例如负载均衡和地理复制)中使用。
出于这些原因,请考虑使用生产级数据存储,例如 PostgreSQL、MySQL 和 SQL Server。有关 Django 对其他数据库的支持信息,请参阅 数据库设置。您还可以使用 Azure SDK for Python 来处理 Azure 存储服务(如表和 Blob)。
定义模型
Django 模型再次是一个从 django.db.model.Models
派生的 Python 类,您将其放在应用程序的 models.py
文件中。在数据库中,每个模型会自动获得一个名为 id
的唯一 ID 字段。所有其他字段都定义为类的属性,使用来自 django.db.models
的类型,例如 CharField
(有限文本)、TextField
(无限文本)、EmailField
、URLField
、IntegerField
、DecimalField
、BooleanField
。DateTimeField
、ForeignKey
和 ManyToMany
等。(有关详细信息,请参阅 Django 文档中的 模型字段参考。)
每个字段都接受一些属性,例如max_length
。blank=True
属性表示该字段是可选的;null=true
表示该值是可选的。还有一个choices
属性,它将值限制为数据值/显示值元组数组中的值。
例如,在models.py
中添加以下类来定义一个数据模型,该模型表示简单消息日志中带日期的条目
from django.db import models
from django.utils import timezone
class LogMessage(models.Model):
message = models.CharField(max_length=300)
log_date = models.DateTimeField("date logged")
def __str__(self):
"""Returns a string representation of a message."""
date = timezone.localtime(self.log_date)
return f"'{self.message}' logged on {date.strftime('%A, %d %B, %Y at %X')}"
模型类可以包含返回从其他类属性计算得出的值的方法。模型通常包含一个__str__
方法,该方法返回实例的字符串表示形式。
迁移数据库
因为您通过编辑models.py
更改了数据模型,所以您需要更新数据库本身。在 VS Code 中,打开一个已激活虚拟环境的终端(使用终端:创建新终端命令,⌃⇧`(Windows、Linux Ctrl+Shift+`)),导航到项目文件夹,并运行以下命令
python manage.py makemigrations
python manage.py migrate
查看migrations
文件夹,查看makemigrations
生成的脚本。您也可以查看数据库本身,以确保模式已更新。
如果运行命令时出现错误,请确保您没有使用之前步骤遗留的调试终端,因为它们可能没有激活虚拟环境。
通过模型使用数据库
有了模型并迁移了数据库,您就可以只使用模型来存储和检索数据。在本节中,您将通过该应用程序添加一个表单页面,您可以在其中记录消息。然后修改主页以显示这些消息。因为您在这里修改了多个代码文件,所以请注意细节。
-
在
hello
文件夹(您拥有views.py
的位置)中,创建一个名为forms.py
的新文件,其中包含以下代码,该代码定义了一个 Django 表单,该表单包含一个从数据模型LogMessage
中提取的字段from django import forms from hello.models import LogMessage class LogMessageForm(forms.ModelForm): class Meta: model = LogMessage fields = ("message",) # NOTE: the trailing comma is required
-
在
templates/hello
文件夹中,创建一个名为log_message.html
的新模板,其中包含以下内容,假设该模板被赋予一个名为form
的变量来定义表单的主体。然后添加一个带有“Log”标签的提交按钮。{% extends "hello/layout.html" %} {% block title %} Log a message {% endblock %} {% block content %} <form method="POST" class="log-form"> {% csrf_token %} {{ form.as_p }} <button type="submit" class="save btn btn-default">Log</button> </form> {% endblock %}
注意:Django 的
{% csrf_token %}
标签提供针对跨站点请求伪造的保护。有关详细信息,请参阅 Django 文档中的跨站点请求伪造保护。 -
在应用程序的
static/hello/site.css
文件中,添加一条规则以使输入表单更宽input[name=message] { width: 80%; }
-
在应用程序的
urls.py
文件中,为新页面添加一个路由path("log/", views.log_message, name="log"),
-
在
views.py
中,定义名为log_message
的视图(如 URL 路由所指)。此视图同时处理 HTTP GET 和 POST 情况。在 GET 情况(else:
部分)中,它只显示您在前面步骤中定义的表单。在 POST 情况中,它将数据从表单检索到数据对象(message
)中,设置时间戳,然后保存该对象,此时该对象将写入数据库# Add these to existing imports at the top of the file: from django.shortcuts import redirect from hello.forms import LogMessageForm from hello.models import LogMessage # Add this code elsewhere in the file: def log_message(request): form = LogMessageForm(request.POST or None) if request.method == "POST": if form.is_valid(): message = form.save(commit=False) message.log_date = datetime.now() message.save() return redirect("home") else: return render(request, "hello/log_message.html", {"form": form})
-
在您准备试用所有内容之前,还需要做最后一步!在
templates/hello/layout.html
中,在“navbar”div 中为消息记录页面添加一个链接<!-- Insert below the link to Home --> <a href="{% url 'log' %}" class="navbar-item">Log Message</a>
-
运行应用程序,然后打开浏览器到主页。选择导航栏上的Log Message链接,该链接应该显示消息记录页面
-
输入一条消息,选择Log,您应该返回到主页。主页尚未显示任何已记录的消息(您将在稍后解决此问题)。您可以随意记录更多消息。如果您愿意,可以使用 SQLite 浏览器等工具查看数据库以确认已创建记录。以只读方式打开数据库,或者记住在使用应用程序之前关闭数据库,否则应用程序将由于数据库被锁定而失败。
-
完成操作后停止应用程序。
-
现在修改主页以显示已记录的消息。首先用下面的标记替换应用程序的
templates/hello/home.html
文件的内容。此模板期望一个名为message_list
的上下文变量。如果它接收到一个变量(使用{% if message_list %}
标签检查),它将遍历该列表({% for message in message_list %}
标签)以生成每条消息的表格行。否则页面会指出还没有记录任何消息。{% extends "hello/layout.html" %} {% block title %} Home {% endblock %} {% block content %} <h2>Logged messages</h2> {% if message_list %} <table class="message_list"> <thead> <tr> <th>Date</th> <th>Time</th> <th>Message</th> </tr> </thead> <tbody> {% for message in message_list %} <tr> <td>{{ message.log_date | date:'d M Y' }}</td> <td>{{ message.log_date | time:'H:i:s' }}</td> <td> {{ message.message }} </td> </tr> {% endfor %} </tbody> </table> {% else %} <p>No messages have been logged. Use the <a href="{% url 'log' %}">Log Message form</a>.</p> {% endif %} {% endblock %}
-
在
static/hello/site.css
中,添加一条规则以稍微格式化表格.message_list th,td { text-align: left; padding-right: 15px; }
-
在
views.py
中,导入 Django 的通用ListView
类,我们将使用它来实现主页from django.views.generic import ListView
-
同样在
views.py
中,将home
函数替换为名为HomeListView
的类,该类派生自ListView
,它将自身绑定到LogMessage
模型并实现一个get_context_data
函数来生成模板的上下文。# Remove the old home function if you want; it's no longer used class HomeListView(ListView): """Renders the home page, with a list of all messages.""" model = LogMessage def get_context_data(self, **kwargs): context = super(HomeListView, self).get_context_data(**kwargs) return context
-
在应用程序的
urls.py
中,导入数据模型from hello.models import LogMessage
-
同样在
urls.py
中,创建一个用于新视图的变量,该变量将以降序方式(意味着它查询数据库)检索最近的五个LogMessage
对象,然后为模板上下文中的数据提供一个名称(message_list
),并识别要使用的模板home_list_view = views.HomeListView.as_view( queryset=LogMessage.objects.order_by("-log_date")[:5], # :5 limits the results to the five most recent context_object_name="message_list", template_name="hello/home.html", )
-
在
urls.py
中,修改指向主页的路径以使用home_list_view
变量# Replace the existing path for "" path("", home_list_view, name="home"),
-
启动应用程序,然后打开浏览器到主页,它现在应该显示消息
-
完成操作后停止应用程序。
使用调试器进行页面模板调试
如前一节所示,页面模板可以包含像{% for message in message_list %}
和{% if message_list %}
这样的过程指令,而不仅仅是被动的、声明性的元素,比如{% url %}
和{% block %}
。因此,您可以在模板中遇到编程错误,就像在任何其他过程代码中一样。
幸运的是,VS Code 的 Python 扩展在调试配置中拥有"django": true
的情况下(您已经拥有),提供了模板调试。以下步骤演示了此功能
-
在
templates/hello/home.html
中,在{% if message_list %}
和{% for message in message_list %}
行上设置断点,如下面的图像中黄色箭头所示 -
在调试器中运行应用程序,然后打开浏览器到主页。(如果您已经在运行调试器,则无需在设置断点后重新启动应用程序;只需刷新页面即可。)观察 VS Code 在模板中
{% if %}
语句处进入调试器,并在Variables窗格中显示所有上下文变量 -
使用Step Over(F10)命令逐步执行模板代码。观察调试器会跳过所有声明性语句,并在任何过程代码处暂停。例如,逐步执行
{% for message in message_list %}
循环,可以让您检查message
中的每个值,并可以让您步进到像<td>{{ message.log_date | date:'d M Y' }}</td>
这样的行。 -
您也可以在Debug Console面板中使用变量。(但是,Django 过滤器(如
date
)目前在控制台中不可用。) -
准备就绪后,选择Continue(F5)以完成应用程序运行,并在浏览器中查看渲染后的页面。完成操作后停止调试器。
可选活动
以下部分介绍了您在使用 Python 和 Visual Studio Code 时可能发现有用的其他步骤。
为环境创建requirements.txt文件
当您通过源代码控制或其他方式共享应用程序代码时,复制虚拟环境中的所有文件是没有意义的,因为接收者可以随时自己重新创建该环境。
因此,开发人员通常会从源代码控制中省略虚拟环境文件夹,而是使用requirements.txt
文件来描述应用程序的依赖项。
虽然您可以手动创建该文件,但您也可以使用pip freeze
命令根据激活环境中安装的精确库来生成该文件
-
使用Python: Select Interpreter命令选择您选择的环境后,运行Terminal: Create New Terminal命令(⌃⇧`(Windows、Linux Ctrl+Shift+`))以打开一个已激活该环境的终端。
-
在终端中,运行
pip freeze > requirements.txt
以在项目文件夹中创建requirements.txt
文件。
任何(或任何构建服务器)接收项目副本的人只需运行pip install -r requirements.txt
命令即可在活动环境中重新安装应用程序依赖的软件包。
注意:
pip freeze
列出了您在当前环境中安装的所有 Python 软件包,包括您当前未使用的软件包。该命令还列出了带有精确版本号的软件包,您可能希望将其转换为范围以将来更灵活地使用。有关更多信息,请参阅 pip 命令文档中的要求文件。
创建超级用户并启用管理界面
默认情况下,Django 为受身份验证保护的 Web 应用程序提供一个管理界面。该界面是通过内置的django.contrib.admin
应用程序实现的,该应用程序默认情况下包含在项目的INSTALLED_APPS
列表(settings.py
)中,身份验证由内置的django.contrib.auth
应用程序处理,该应用程序也默认情况下包含在INSTALLED_APPS
中。
执行以下步骤以启用管理界面
-
通过在 VS Code 中为您的虚拟环境打开一个终端,然后运行命令
python manage.py createsuperuser --username=<username> --email=<email>
来在应用程序中创建一个超级用户帐户,当然,将<username>
和<email>
替换为您的个人信息。运行该命令时,Django 会提示您输入并确认您的密码。请务必记住您的用户名和密码组合。这些是您用于对应用程序进行身份验证的凭据。
-
在项目级
urls.py
(在本教程中为web_project/urls.py
)中添加以下 URL 路由,以指向内置的管理界面# This path is included by default when creating the app path("admin/", admin.site.urls),
-
运行服务器,然后打开浏览器到应用程序的 /admin 页面(例如,在使用开发服务器时为
http://127.0.0.1:8000/admin
)。 -
一个登录页面将会出现,由
django.contrib.auth
提供。输入你的超级用户凭据。 -
一旦你完成身份验证,你将会看到默认的管理页面,通过它你可以管理用户和组。
你可以根据自己的喜好自定义管理界面。例如,你可以提供编辑和删除数据库中条目的功能。有关进行自定义的更多信息,请参考 Django 管理站点文档。
使用 Docker 扩展创建 Django 应用程序的容器。
Docker 扩展 使得从 Visual Studio Code 轻松构建、管理和部署容器化应用程序。如果你想学习如何为本教程中开发的 Django 应用程序创建 Python 容器,请查看 Python 在容器中 教程,该教程将逐步指导你完成以下操作:
- 创建一个
Dockerfile
文件,描述一个简单的 Python 容器。 - 构建、运行并验证 Django 应用程序的功能。
- 调试运行在容器中的应用程序。
后续步骤
恭喜你完成了本教程关于在 Visual Studio Code 中使用 Django 的演练!
本教程的完整代码项目可以在 GitHub 上找到:python-sample-vscode-django-tutorial。
在本教程中,我们只是略微触及了 Django 的全部功能。请务必访问 Django 文档 和 官方 Django 教程,以了解更多关于视图、模板、数据模型、URL 路由、管理界面、使用其他类型的数据库、部署到生产环境等方面的详细信息。
要在生产网站上尝试你的应用程序,请查看教程 使用 Docker 容器将 Python 应用程序部署到 Azure 应用服务。Azure 还提供一个标准容器,Linux 上的应用服务,你可以从 VS Code 内部将 Web 应用程序部署到该容器。
你可能还想查看 VS Code 文档中与 Python 相关的以下文章