教程:在 Visual Studio 中使用 Django 提供静态文件和实现模板继承

本文介绍教程系列中的步骤 3 在 Visual Studio中使用 Django Web 框架。

在本教程系列的上一步骤中,创建了一个具有单个自包含 HTML 页面的小型 Django 应用。 新式 Web 应用通常由许多页面组成,并使用 CSS 和 JavaScript 文件等共享资源提供一致的样式和行为。 在步骤 3 中,使用 Visual Studio 项模板将内容添加到 Django 项目并扩展应用程序的功能。

在本教程的步骤 3 中,你将了解如何:

  • 使用 Visual Studio 项模板通过样本代码快速添加新文件
  • 从 Django 代码提供静态文件
  • 向 Django 应用添加更多页面
  • 使用模板继承创建页眉和跨页面导航

先决条件

在 Visual Studio 中浏览项模板

开发 Django 应用程序时,通常会添加更多 Python、HTML、CSS 和 JavaScript 文件。 对于每种文件类型(以及可能需要用于部署的 web.config 等其他文件),Visual Studio 提供了便捷的 项目模板,帮助您快速入门。 可以使用这些模板通过样板代码快速添加新类型的文件。

  1. 若要查看可用的模板,请转到 Visual Studio 中的 解决方案资源管理器 并打开项目结构。

  2. 右键单击要在其中创建新文件的文件夹,然后选择 添加>新项。 “添加新项”对话框打开:

    显示 Visual Studio 2022 中“添加新项”对话框中可用模板的屏幕截图。

    显示 Visual Studio 中“添加新项”对话框中可用模板的屏幕截图。

  3. 若要使用模板,请选择所需的模板,输入文件的名称,然后选择 添加

Visual Studio 将文件添加到当前项目,并标记源代码管理所做的更改。

了解 Visual Studio 如何标识项模板

Visual Studio 项目文件(.pyproj) 包含项目类型标识符,将该文件标记为 Python 项目。 Visual Studio 使用此类型标识符来识别并仅显示适合项目类型的项模板。 Visual Studio 遵循此方法,为许多项目类型提供丰富的项模板,而无需每次都要求你对其进行排序。

在应用中提供静态文件

在使用 Python 生成的 Web 应用中(使用任何框架),Python 文件始终在 Web 主机的服务器上运行,永远不会传输到用户的计算机。 其他文件(如 CSS 和 JavaScript)仅供浏览器使用,因此主机服务器只需在请求时 as-is 传递它们。 这些类型的文件称为“静态”文件,Django 可以自动交付这些文件,而无需编写任何代码。

默认情况下,Django 项目设置为从应用的 静态 文件夹中提供静态文件。 Django 项目的 settings.py 文件中的以下代码可以实现此行为:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = posixpath.join(*(BASE_DIR.split(os.path.sep) + ['static']))

可以使用喜欢的任何文件夹结构,在应用的 静态 文件夹中组织文件,并使用 静态 文件夹中的相对路径来引用文件。

在 HTML 模板中使用静态 CSS 文件

按照以下步骤将 CSS 文件添加到应用,然后在 index.html 模板中使用 CSS 样式表:

  1. 解决方案资源管理器中,右键单击项目中的 HelloDjangoApp 文件夹,选择 添加>新文件夹,并将文件夹命名 为静态

  2. 右键单击 静态 文件夹,然后选择“添加>新项

  3. 在“添加新项 对话框中,选择 样式表 模板,将文件命名为 site.cs,然后选择 添加

    Visual Studio 将 site.css 文件添加到项目中,并在编辑器中打开该文件。 下面是更新的 Django 项目结构的示例:

    显示解决方案资源管理器中的静态文件结构的屏幕截图。

  4. site.css 文件的内容替换为以下样式:

    .message {
        font-weight: 600;
        color: blue;
    }
    
  5. HelloDjangoApp/templates/index.html 文件的内容替换为以下标记:

    <html>
       <head>
          <title>{{ title }}</title>
          {% load static %} <!-- Instruct Django to load static files -->
          <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
       </head>
       <body>
          <span class="message">{{ message }}</span>{{ content }}
       </body>
    </html>
    

    此代码将教程系列步骤 2 中的 <strong> HTML 元素替换为引用 message 样式类的 <span> 元素。 以这种方式使用样式类可让你更灵活地设置 HTML 元素的样式。

  6. 通过选择“文件”>“全部保存”或使用 Ctrl+Shift+S 键盘快捷方式来保存项目更改。 (此步骤不是必需的,因为在开发项目时,Visual Studio 会自动保存文件。

  7. 运行项目并观察结果。 完成后,停止应用。

  8. (可选)可以将更改提交到源代码管理并更新远程存储库。 有关详细信息,请参阅本教程系列步骤 2 中的 提交对源代码管理 的更改。

使用 {% load static %} 标签

index.html 文件中必须存在 {% load static %} 语句,然后站点才会相对引用 HTML 元素中的静态文件,例如 <head><body> 在本部分所示的示例中,“静态文件”是指自定义 Django 模板标记集。 通过标记集,可以使用 {% static %} 语法来引用静态文件。 如果没有 {% load static %} 标记,应用运行时会看到异常。

在没有 {% load static %} 标记的情况下添加引用

还可在不使用 {% load static %} 标记的情况下设置对 HTML 标记中静态文件的相对引用。 在这种情况下,指定 Django 项目文件夹层次结构中 静态 文件夹的位置:

<html>
    <head>
        <title>{{ title }}</title>
        <link rel="stylesheet" type="text/css" href="../../static/site.css" />
    </head>
    <body>
        <span class="message">{{ message }}</span>{{ content }}
    </body>
</html>

组织静态文件和文件夹

可以根据项目需求,在 静态 文件夹中添加其他 CSS、JavaScript 和 HTML 文件。 组织静态文件的典型方法是创建名为 字体的子文件夹脚本,以及 内容(对于样式表和任何其他文件)。 在每个情况下,请记住将文件夹包含在 {% static %} 引用中的相对文件路径中。

将页面添加到 Django 应用程序

将另一页添加到 Django 应用程序涉及以下任务:

  • 添加定义视图的 Python 函数
  • 为页面的 HTML 标记添加模板
  • 更新 Django 项目的 urls.py 文件中的 URL 路由

按照以下步骤将 About(/about) 页面添加到 HelloDjangoApp 项目中,并从主页链接到该页面:

  1. 解决方案资源管理器中,右键单击项目中的 模板/HelloDjangoApp 文件夹,然后选择“添加>新项

    提示

    如果在 “添加”菜单上没有看到 “新建项” 命令,请确保停止 Django 应用,以便 Visual Studio 根据需要退出调试模式。

  2. 在“添加新项 对话框中,选择 HTML 页面 模板,将文件命名为 about.html,然后选择 添加

  3. about.html 文件的内容替换为以下 HTML 标记:

    <html>
       <head>
          <title>{{ title }}</title>
          {% load static %}
          <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
       </head>
       <body>
          <div><a href="home">Home</a></div>
          {{ content }}
       </body>
    </html>
    

    在后续步骤中,将主页的显式链接替换为导航栏。

  4. HelloDjangoApp/views.py 文件中,添加一个名为 about 的函数,该函数使用模板:

    def about(request):
       return render(
          request,
          "HelloDjangoApp/about.html",
          {
             'title' : "About HelloDjangoApp",
             'content' : "Example app page for Django."
          }
       )
    
  5. 在 Django 项目的 BasicProject/urls.py 文件中,将 about 页的路径添加为 urlPatterns 数组中的最后一项:

    # Django processes URL patterns in the order they appear in the array
    urlpatterns = [
       re_path(r'^$', HelloDjangoApp.views.index, name='index'),
       re_path(r'^home$', HelloDjangoApp.views.index, name='home'),
       re_path(r'^about$', HelloDjangoApp.views.about, name='about')
     ]
    
  6. templates/HelloDjangoApp/index.html 文件中,添加以下标记作为 <body> 元素中的第一个语句:

    <div><a href="about">About</a></div>
    

    此标记为 Django 应用添加一个指向 /about 页面的链接。 在后面的步骤中,请将此链接替换为导航栏。

  7. 保存项目更改,然后再次运行项目。 浏览到 /about 页面,并检查各个应用页面之间的导航。

  8. 完成后,停止应用。

导航到“首页”页面

如果尝试浏览到正在运行的应用的 /index 页面,则会看到未找到 页面(404) 错误。

尽管 HelloDjangoApp/views.py 文件具有名为 index的函数,但 Django 项目的 BasicProject/urls.py 文件中的 URL 路由模式不包含与字符串 index匹配的正则表达式。 在应用“索引”页上当前显示的表达式为 ^$。 若要匹配字符串 index,需要为模式 ^index$添加另一个 URL 条目。

下一部分描述如何更好地在页面模板中使用 {% url '<pattern_name>' %} 标记来引用模式的名称。 在这种情况下,Django 会为你创建正确的 URL。 例如,可以将 templates/HelloDjangoApp/about.html 文件中的 <div><a href="home">Home</a></div> 标记替换为标记 <div><a href="{% url 'index' %}">Home</a></div>'index' 字符串的使用现在有效,因为 urls.py 文件中的第一个 URL 模式命名为 'index'。 还可以使用 'home' 来引用第二种模式。

使用模板继承来处理页眉和导航

许多 Web 应用都有一个带有品牌标识的标题和一个导航栏,它提供最重要的页面链接、弹出菜单等功能,而不是在每个页面上使用显式的导航链接。 为了确保应用中的一致性,标题和导航栏在所有页面中都应相同,但不需要在每个页面模板中重复相同的代码。 可以在单个文件中定义所有页面的常见部分。

Django 的模板化系统提供了两种跨多个模板重复使用特定元素的方法:

  • “包含”是可以使用语法 {% include <template_path> %} 在引用模板的特定位置插入的另一个页面模板。 如果要在代码中动态更改路径,也可以使用变量。 包含通常用于页面主体,在页面特定位置拉入共享模板。

  • “继承”使用页面模板开头的 {% extends <template_path> %} 语法来指定共享基模板,然后会在此模板上生成引用模板。 继承通常用于定义应用的页面的共享布局、导航栏和其他结构。 此方法要求引用模板仅添加或修改基模板称为“块”的特定区域。

对于这两种方法,<template_path> 值都与应用 模板 文件夹(也允许.././)相对。

基模板使用 {% block <block_name> %}{% endblock %} 标记来描述块。 如果引用模板使用具有相同块名称的标记,则引用模板中的块内容将替代基模板中的匹配块。

以下步骤演示模板继承:

  1. 解决方案资源管理器中,右键单击 模板/HelloDjangoApp 文件夹,并从 HTML 页面 模板创建新文件,其名称为 layout.html

  2. layout.html 文件的内容替换为以下 HTML 标记:

    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8" />
       <title>{{ title }}</title>
       {% load static %}
       <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
    </head>
    
    <body>
       <div class="navbar">
          <a href="/" class="navbar-brand">Hello Django</a>
          <a href="{% url 'home' %}" class="navbar-item">Home</a>
          <a href="{% url 'about' %}" class="navbar-item">About</a>
       </div>
    
       <div class="body-content">
          {% block content %}
          {% endblock %}
          <hr/>
          <footer>
             <p>&copy; 2024</p>
          </footer>
       </div>
    </body>
    </html>
    

    此模板包含一个名为 content的块,这个块定义了引用页面需要替换的所有内容。

  3. HelloDjangoApp/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;
    }
    

    这些样式定义为本练习生成了一个有趣的结果。 本演练不演示响应式设计。

  4. templates/HelloDjangoApp/index.html 文件的内容替换为以下代码:

    {% extends "HelloDjangoApp/layout.html" %}
    {% block content %}
    <span class="message">{{ message }}</span>{{ content }}
    {% endblock %}
    

    index 模板现在引用基模板并替代 content 块。 可以看到,使用继承可以简化此模板。

  5. 将 templates/HelloDjangoApp/about.html 文件的内容替换为以下代码,使得 about 模板也引用基模板并重写 content 块:

    {% extends "HelloDjangoApp/layout.html" %}
    {% block content %}
    {{ content }}
    {% endblock %}
    
  6. 再次运行应用并观察结果。 使用导航栏链接在应用页面之间切换。

    屏幕截图,显示修改后的 Django 应用,该应用使用模板继承在所有页面上呈现标题和导航栏。

  7. 完成后,停止应用并保存项目更改。

  8. 由于对应用进行了重大更改,因此最好将更改保存到 Git 存储库。 有关详细信息,请参阅本教程系列步骤 2 中的 提交对源代码管理 的更改。

下一步