Django 模板语言:标签和过滤器

举报
Yuchuan 发表于 2021/09/24 17:26:27 2021/09/24
【摘要】 Django 模板标签和过滤器为您提供了一种以可重用方式构建 HTML 输出的强大方法。模板以它们自己的语言定义,以便将业务逻辑与显示逻辑分开。标签就像语言的关键字和功能,而过滤器允许您在显示之前修改现有数据。

目录

Django是一个强大的框架,用于在 Python 中创建 Web 应用程序。它的功能包括数据库模型路由 URL身份验证用户管理管理工具和模板语言。您可以编写可重用的 HTML,这些 HTML 会根据您传递给模板语言的数据进行更改。Django 模板使用标签和过滤器来定义一种类似于 Python 但不是 Python 的迷你语言。

您将通过用于编写可重用 HTML 的标签和过滤器来了解 Django 模板。

在本教程中,您将学习如何:

  • 编写、编译和呈现Django 模板
  • 使用视图中的render()快捷方式快速使用模板
  • 模板中的条件和循环使用模板标签
  • 创建具有继承和包含功能的可重用模板
  • 通过模板过滤器修改数据的呈现方式

创建 Django 项目

要试验 Django 模板,您将需要一个项目,以便您可以使用代码。您将构建 MoviePalace:世界上最小、最简单的电影网站。有关启动新项目的更详细示例,您可以阅读Django 入门第 1 部分:构建投资组合应用程序

Django 不是标准 Python 库的一部分,因此您首先需要安装它。在处理第三方库时,您应该使用虚拟环境。要复习虚拟环境,您可以阅读Python Virtual Environments: A Primer

一旦你有了一个虚拟环境,运行以下命令开始:

 1$ python -m pip install django==3.2.5
 2$ django-admin startproject MoviePalace
 3$ cd MoviePalace
 4$ python manage.py startapp core

第 1 行使用pip. 在第 2 行,该django-admin命令创建了一个名为 的新 Django 项目MoviePalace。Django 项目由应用程序组成,您的代码就在其中。第四个命令创建一个名为core.

你几乎准备好了。最后一步是将您新创建的core应用程序告诉 Django 。您可以通过编辑MoviePalace/settings.py文件并将其添加"core"到以下列表中来完成此操作INSTALLED_APPS

33INSTALLED_APPS = [
34    "django.contrib.admin",
35    "django.contrib.auth",
36    "django.contrib.contenttypes",
37    "django.contrib.sessions",
38    "django.contrib.messages",
39    "django.contrib.staticfiles",
40    "core",
41]

随着core注册为一个应用程序,你现在就可以编写包含模板的视图。

准备使用 Django 模板

Django 是在一家报纸上创建的,用于帮助快速构建 Web 应用程序。该框架的目标之一是将业务逻辑的关注点与表示逻辑的关注点分开。

Web 设计人员,而不是 Python 程序员,经常在论文中进行 HTML 开发。因此,开发人员决定不允许在模板语言中执行 Python。这一决定简化了设计人员需要了解的内容,并出于安全原因对他们的代码进行了沙盒处理。最终结果是一个单独的迷你语言。这种方法与PHP 方法形成对比,后者将代码直接嵌入到 HTML 中。

编译和渲染 Django 模板

Django 模板允许您在渲染上下文中动态更改输出内容。您可以将模板视为套用信函,其中信函的内容包括可以插入信息的位置。您可以使用不同的数据多次运行渲染过程,每次都会得到不同的结果。

Django 提供TemplateContext类来表示正在呈现的字符串模板和在生成过程中使用的数据。的Context类是一个包装到一个dict和提供键-值对来填充所生成的内容。渲染模板的结果可以是任何文本,但通常是 HTML。毕竟,Django一个 Web 框架。

是时候构建您的第一个模板了。要查看实际操作,您首先需要一个视图。将以下代码添加到core/views.py

 1# core/views.py
 2from django.http import HttpResponse
 3from django.template import Context, Template
 4
 5def citizen_kane(request):
 6    content = """{{movie}} was released in {{year}}"""
 7    template = Template(content)
 8    context = Context({"movie": "Citizen Kane", "year": 1941})
 9
10    result = template.render(context)
11    return HttpResponse(result)

在此视图中,您会看到构成 Django 模板语言的一些主要概念:

  • 第 6 行包含对movie和 的引用year。这类似于 Python f-string。双大括号或小胡子括号表示 Django 在呈现模板时替换的项目。
  • 第 7 行Template通过传入指定模板的字符串来实例化一个对象。
  • 第 8 行Context通过用字典填充它来创建一个对象。该Context对象包含 Django 呈现模板时模板可用的所有数据。该模板包含两个要替换的项目:{{movie}}with"Citizen Kane"{{year}}with 1941
  • 第 10行调用了.render()生成结果的方法。
  • 第 11 行返回包装在HttpResponse对象中的渲染内容。

要对此进行测试,您需要在浏览器中提供此视图,因此您需要添加一个路由。修改MoviePalace/urls.py如下:

# MoviePalace/urls.py
from django.urls import path
from core import views

urlpatterns = [
    path("citizen_kane/", views.citizen_kane),
]

确保您使用的是安装 Django 的虚拟环境,然后运行 ​​Django 开发服务器查看结果:

$ python manage.py runserver

通过访问运行您的视图http://127.0.0.1:8000/citizen_kane/

HttpResponse对象将此内容作为 HTML 返回,但由于字符串不包含任何标签,您的浏览器会将其视为<body>标签内的文本。它返回格式错误的 HTML,但现在已经足够使用了。如果一切顺利,您应该会看到使用上下文中的数据呈现的模板:

Citizen Kane was released in 1941

您的模板已编译,Django的替换movieyear变量与Citizen Kane1941

配置 Django 以加载文件模板

在 Web 应用程序中,您最可能使用的模板是输出 HTML——大量的 HTML。Django 模板语言旨在简化此过程。与前面的示例不同,您通常不会在视图中使用模板字符串。相反,您从其他文件加载模板。

要从磁盘加载模板,您首先需要告诉 Django 在哪里可以找到它。里面MoviePalace/settings.py,修改里面的"DIRS"TEMPLATES

 1TEMPLATES = [
 2    {
 3        "BACKEND": "django.template.backends.django.DjangoTemplates",
 4        "DIRS": [
 5            BASE_DIR / "templates",
 6        ],
 7        "APP_DIRS": True,
 8        "OPTIONS": {
 9            "context_processors": [
10                "django.template.context_processors.debug",
11                "django.template.context_processors.request",
12                "django.contrib.auth.context_processors.auth",
13                "django.contrib.messages.context_processors.messages",
14            ],
15        },

在命令创建的默认settings.py文件中django-adminDIRS列表为空。Django 现在将在名为MoviePalace/templates. 请注意,Django 使用双文件夹结构进行自己的配置。例如,settings.pyMoviePalace/MoviePalace. 模板的目录应该在项目根目录中,而不是在配置目录中。

APP_DIRS第 7 行 is 时True,Django 还会在 app 子目录中查找模板。Django 期望应用程序模板templates位于应用程序文件夹下命名的目录中。

在 Django 3.1 之前显示隐藏

您如何决定存储模板的位置?如果您的应用程序可在其他项目中重复使用并且具有特定于它的模板,则将模板保留在应用程序中。否则,请将您的模板放在项目模板目录中。有关如何构建 Django 项目的更多信息,请参阅 Django入门课程中有关 Django 双文件夹结构的课程。

MoviePalace/settings.py文件进行更改后,不要忘记创建templates目录:

$ pwd
/home/realpython/MoviePalace
$ mkdir templates

配置完成并创建目录后,您现在可以从文件加载模板。

从文件加载 Django 模板

让我们使用文件重建《公民凯恩》体验。创建templates/simple.txt并添加citizen_kane()视图中使用的模板字符串:

{{movie}} was released in {{year}}

您可以编写代码以将文件作为字符串加载、构建Template对象并执行您在citizen_kane()视图中所做的相同操作,或者您可以使用render()快捷方式,它为您完成所有这些。将以下内容添加到您的core/views.py文件中:

# core/views.py
⋮
from django.shortcuts import render

def casablanca(request):
    return render(
        request, "simple.txt", {"movie": "Casablanca", "year": 1942}
    )

新视图到位后,不要忘记添加一个路由到MoviePalace/urls.py

# MoviePalace/urls.py
from django.urls import path
from core import views

urlpatterns = [
    path("citizen_kane/", views.citizen_kane),
    path("casablanca/", views.casablanca),
]

访问http://127.0.0.1:8000/casablanca/应该产生与公民凯恩示例类似的结果:

Casablanca was released in 1942

render()快捷方式呈现模板的常用方法。Template直接使用对象仅在极少数情况下完成,例如当您想为用户提供模板的力量时。

Template直接使用的一个示例可能是允许您的用户输入套用信函。套用信函可能包含变量,例如信函的收件人。通过允许用户使用 Django 模板,您可以利用内置的变量替换机制来替换收件人的姓名。

选择模板语言

Django 支持多种模板引擎。它附带两个:

  • Django 模板语言:原始的 Django 模板语言,也是您在本教程中学习的语言
  • Jinja2:以前是一个仅限第三方的库,现在包含在 Django 中,但不在本教程的范围内

您可以通过编辑中的TEMPLATES值来更改使用的模板引擎MoviePalace/settings.py

 1TEMPLATES = [
 2    {
 3        "BACKEND": "django.template.backends.django.DjangoTemplates",
 4        "DIRS": [
 5            BASE_DIR / "templates",
 6        ],
 7        "APP_DIRS": True,
 8        "OPTIONS": {
 9            "context_processors": [
10                "django.template.context_processors.debug",
11                "django.template.context_processors.request",
12                "django.contrib.auth.context_processors.auth",
13                "django.contrib.messages.context_processors.messages",
14            ],
15        },

BACKEND3 行的设置是您指定渲染引擎的地方。您可以通过更改引擎BACKEND的虚线路径模块名称来选择 Django 模板引擎或 Jinja2引擎:

  • django.template.backends.django.DjangoTemplates
  • django.template.backends.jinja2.Jinja2

第三方模板引擎也可用。使用它们需要通过安装库pip并将BACKEND值更改为引擎的虚线路径名称。

本教程的其余部分将只关注原始 Django 模板后端,为您在 Django 项目中创建 HTML 奠定坚实的基础。

学习 Django 模板、标签和过滤器

到目前为止,您已经看到了包含简单变量替换的模板。Django 模板语言比这更深入。除了 Python 自己的迷你语言之外,您可以访问您在 Python 中习惯的许多结构和控件。

Django 模板标签和过滤器

Django 模板语言具有三种控制渲染内容的方式:valuestagsfilters。您放入模板中的所有内容都将按照您编写的方式呈现。在本教程中,您将了解模板语言的三个主要部分:

  1. 解释的数据,你用双大括号注明,{{ value }}
  2. Tags,你用大括号和百分号记下,{% tag_name %}
  3. 过滤器,它修改解释的数据,并使用管道运算符 ( |) 进行应用,例如{{ value | filter }}

正如您在上一节中看到的,当 Django 将模板呈现为文本时,它使用一个名为Context. 上下文是模板呈现的状态。除了包含要用双大括号呈现的解释数据之外,Context对象的内容还可用于进行逻辑决策。

标签就像模板语言的关键字和函数。在 Python 中,关键字和函数提供控制流和构建代码的工具。同样,Django 的内置标签提供继承、条件操作、循环、注释和文本管理。例如,{% lorem %}标签在渲染时被替换为示例lorem ipsum文本。

Django 过滤器在双大括号内运行,可让您更改显示数据的呈现方式。例如,date过滤器格式化一个日期时间对象,类似于strftime()Python 中的工作方式。如果Context字典包含datetime名为的对象today{{ today | date:"Y"}}则将date过滤器应用于today,返回年份。

本教程的其余部分将指导您了解常见的标签和过滤器,并给出您如何使用它们的示例。

模板继承和包含

HTML 中有很多样板文件。大多数网站的每个页面都有一个共同的外观。呈现的每个页面通常会重复相同的页眉和页脚,其中包括相同的样式表,并且通常包括用于度量和测量的相同 JavaScript 文件。在每个页面上手动重复此操作意味着进行更改将需要大量工作。模板继承和包含来拯救你!

有两种方法可以将 Django 模板的各个部分组合在一起。继承的工作方式类似于 Python 中的类继承,模板覆盖其父级的值。包含将内容从另一个模板注入到模板中。这类似于#includeC 编程语言中的指令。

要查看这些操作,请创建templates/base.html

 1<!-- templates/base.html -->
 2<html>
 3<body>
 4  {% block heading %}
 5    <h1>Movie Palace</h1>
 6  {% endblock heading %}
 7
 8  {% block content %}
 9  {% endblock content %}
10</body>
11</html>

这个声明就像面向对象编程中的基类。您可以单独使用它,也可以设置其他模板来继承它。如果此模板按原样呈现,则{% block %}标签的内容将按原样显示。在子级不覆盖块的情况下,这提供了有用的默认值。

base.html,有一个标题说<h1>Movie Palace</h1>,没有内容。当另一个模板从这个模板继承时,魔法就会发生。在子模板中,您可以选择覆盖任何已定义的块。一种常见的做法是用content页面的内容填充块,同时将样板 HTML 留在此基本文件中。创建一个继承自base.html被调用的模板templates/falcon.html

 1<!-- templates/falcon.html -->
 2{% extends "base.html" %}
 3
 4{% block heading %}
 5  {{block.super}}
 6  <h2>The stuff that dreams are made of</h2>
 7{% endblock heading %}
 8
 9{% block content %}
10  <p>
11    {% include "simple.txt" %}
12  </p>
13{% endblock content %}

falcon.html文件显示了两件事:继承包含。您可以使用{% extends %}标记继承父文件。这里,falcon.html继承自base.html. Djangobase.html完整地呈现文件,除非孩子falcon.html覆盖了一个块。例如, 中的content部分falcon.html覆盖 中具有相同名称的块base.html

block部分内部,定义了一个特殊变量:{{block.super}}。此变量包含父块中的任何内容。在第 5 行,父块引入了<h1>Movie Palace</h1>标题,而在第 6 行将falcon.html加入<h2>到块中。

除了继承,还可以进行包含。在第 11 行,该{% include %}标签插入了 的内容simple.txt。这允许您重用 HTML 片段。在这里,它重用了最初为casablanca()视图定义的模板。

要查看所有这些操作,您需要一个新视图来呈现它们。在中创建以下内容core/views.py

# core/views.py
⋮
def maltese_falcon(request):
    return render(
        request,
        "falcon.html",
        {"movie": "Maltese Falcon", "year": 1941},
    )

此视图几乎与 相同casablanca(),只是它渲染falcon.html并传入适当的电影数据。MoviePalace/urls.py使用maltese_falcon视图的路由更新您的文件,然后访问该页面:

使用 extends 标签呈现的继承结果

你覆盖了标题,你包含了simple.txt,Django 用 Maltese Falcon 电影数据渲染了它。

在 内部falcon.html{% extends %}标签对父模板的名称进行了硬编码。这是最常见的情况,但可以在上下文变量中命名父模板。这个技巧可以让你在登录和公共状态下使用相同的子页面,根据情况更改父模板。

falcon.html模板仅使用一级继承,但您不仅限于此。孙子可以从子孙那里继承,而子孙又可以从父母那里继承。您可以根据需要拥有多个层来组织您的输出。

探索通用模板标签

您可以利用 Django 3.2.5 包含的超过 25 个内置标签。这些标签就像模板语言的关键字和功能。它们允许您执行条件逻辑、循环、继承、文本操作等等。

条件代码

在Python中,您使用ifelifelse关键字来有条件地执行代码。在 Django 模板中,您可以使用标签来完成同样的事情。

要查看这些标签的实际效果,您需要一个包含更多数据的视图。编辑您的core/views.py文件并添加以下函数:

# core/views.py
⋮
def psycho(request):
    data = {
        "movie": "Psycho",
        "year": 1960,
        "is_scary": True,
        "color": False,
        "tomato_meter": 96,
        "tomato_audience": 95,
    }
    return render(request, "psycho.html", data)

psychoto添加相应的路由MoviePalace/urls.py,然后创建templates/psycho.html

 1<!-- templates/psycho.html -->
 2{% extends "base.html" %}
 3
 4{% block content %}
 5  <p>
 6    {{movie}} was released in {{year}}.  It was {% if not is_scary %}not
 7    {% endif %}scary.
 8  </p>
 9
10  <p>
11    {% if color %}
12      Color
13    {% else %}
14      Black and white 
15    {% endif %}
16  </p>
17
18  <p>
19    {% if THX %}
20      Sound was awesome
21    {% endif %}
22  </p>
23
24  <p>
25    {% if tomato_meter > tomato_audience %}
26      Critics liked it better than audience
27    {% elif tomato_meter == tomato_audience %}
28      Critics liked it the same as audience
29    {% else %}
30      The audience liked it better than the critics
31    {% endif %}
32  </p>
33
34  <p>Copyright <b>MoviePalace</b></p>
35{% endblock content %}

{% if %}标签的工作原理是Python的if关键字。如果测试的条件是True,则呈现块。

  • 第 6 行到第 7 行显示了使用内联 if 条件,其is_scary值用not关键字取反。
  • 第 11 到 15 行显示了多行 if 条件的使用。这个条件块还包含一个{% else %}子句。if但是,与在 Python 中编写语句不同的是,不要忘记结束{% endif %}标记。
  • 第 19 行检查THXDjango 找不到的变量。一个不在上下文中的变量被考虑False,所以这个关于声音质量的块不会被渲染。
  • 第 25 到 31 行显示了条件与布尔比较运算符的使用。您可以在标签内使用在 Python 中使用的相同类型的运算符。

如果你运行你的开发服务器并访问视图,你会注意到条件标签已经起作用了:

使用 if、elif、else 和 endif 条件标记呈现的示例页面

条件标记使您可以控制 HTML 块的显示,其功能与 Python 代码中的条件部分相同。在psycho()视图中处理数据,看看它如何改变条件块的输出。

循环

有一个用于循环的 Django 模板标签:{% for %}. 它使用与 Pythonfor语句类似的语法,并提供一些内置变量,提供有关您在迭代中的位置的信息。

到目前为止,电影视图中的数据很少,没有什么可以循环的。要使用循环,您需要向 中添加另一个视图core/views.py

# core/views.py
⋮
def listing(request):
    data = {
        "movies": [
            (
                "Citizen Kane",   # Movie
                1941,             # Year
            ),
            (
                "Casablanca",
                1942,
            ),
            (
                "Psycho",
                1960,
            ),
        ]
    }
    return render(request, "listing.html", data)

该视图有一个名为 的上下文变量movies,它是一个列表。您将要构建的模板将使用循环标记来遍历此列表。创建templates/listing.html如下:

 1<!-- templates/listing.html -->
 2{% extends "base.html" %}
 3
 4{% block content %}
 5  <h2> Movies</h2>
 6  <ul>
 7    {% for movie in movies %}
 8      <li>
 9        #{{forloop.counter}} {{movie.0}} was released in {{movie.1}}
10      </li>
11    {% endfor %}
12  </ul>
13
14  <h2> Goodies </h2>
15  <ul>
16    {% for goodie in confectionaries %}
17      <li> {{goodie.0}} &mdash; ${{goodie.1}}</li>
18    {% empty %}
19      <li> <i>There are no goodies available</i> </li>
20    {% endfor %}
21  </ul>
22{% endblock content %}

第 7 到 11 行包含一个{% for %}块,类似于forPython 中的关键字。该块迭代movies并分配一个movie在每个循环中命名的局部变量。在块内部,您编写 HTML,利用双大括号对来显示<li>标签内的内容。

第 8 行到第 10 行在每次迭代中重复一次。该循环使用了一个名为 的特殊对象forloop。这是 Django 在模板上下文中插入的局部变量。该对象有多个成员,每个成员都包含有关当前循环迭代的信息:

Variable Description
forloop.counter 1-based index number of the iteration
forloop.counter0 0-based index number of the iteration
forloop.revcounter Number of iterations left in the loop (1-indexed)
forloop.revcounter0 Number of iterations left in the loop (0-indexed)
forloop.first True if this is the first iteration
forloop.last True if this is the last iteration
forloop.parentloop Contains the context of the parent loop inside nested loops

让我们再检查一下循环块内的行:

 7<!-- From inside of templates/listing.html -->
 8<li>
 9  #{{forloop.counter}} {{movie.0}} was released in {{movie.1}}
10</li>

的内容movies是元组列表。每个元组包含电影的名称和年份。Django 模板标签不允许使用下标。不像在 Python 中那样使用方括号访问元组或列表中的值,而是使用数字作为对象的属性。的值{{movie.0}}{{movie.1}}是的第一和第二值movie元组。

Django 循环还支持一个名为{% empty %}listing.html再次打开此标签的示例:

13<!-- From inside of templates/listing.html -->
14{% for goodie in confectionaries %}
15  <li> {{goodie.0}} &mdash; ${{goodie.1}}</li>
16{% empty %}
17  <li> <i>There are no goodies available</i> </li>
18{% endfor %}

这个标签就像一个else子句。如果{% for %}标记中没有任何内容可迭代,Django 将运行该{% empty %}块。

{% empty %}标签比缠绕更为方便{% for %}在一个块{% if %}的块,以实现相同的结果。在这种情况下,confectionaries上下文中没有定义。Django 模板语言将缺失值视为空值,因此它呈现{% empty %}块的一部分。

在 中添加路由MoviePalace/urls.py,启动 Django 开发服务器,然后访问http://127.0.0.1:8000/listing/以查看结果:

Django 模板示例,MoviePalace 列表

还支持另一种类似循环的标签:{% cycle %}. 这个标签接受一系列参数,并在每次调用时依次返回每个参数:

{% for movie in movies %}
    <tr class="{% cycle 'row1' 'row2' %}">
    ...
    </tr>
{% endfor %}

{% cycle %}参数用完时,它会循环回到开头。最常见的用途是向表格添加条纹,交替每一行的样式值:

使用循环标记的条带化表示例

您可以使用{% for %}标签实现相同的结果,但这种方法需要更多代码。

注释

尽管您可以使用 以 HTML 格式编写评论<!-- -->,但下载到用户浏览器的响应包括这些评论。Django 包含一个{% comment %}标签,其内容被完全剥离:

{% comment %}
    Nothing to see here!
{% endcomment %}

您还可以将字符串参数包含到{% comment %}用作注释的标签中。这可能看起来有点奇怪,但如果您要注释掉代码,它会很有用。您使用块注释掉代码,然后使用注释来提醒自己注释掉代码的原因。

特殊的角色

默认情况下,Django 模板渲染器会自动转义它渲染的任何变量。如果字符串包含 HTML 特有的字符,例如HTML 标签中使用的尖括号 ( <>) ,这会尝试防止您的 HTML 被损坏。该{% autoescape %}标签允许您控制此行为:

{% autoescape off %}
    {{ content }}
{% endautoescape %}

所述{% autoescape %}标签取的单个参数onoff,把擒纵机构打开或关闭,分别。考虑以下模板:

<pre>
{% autoescape on %}
    Escaped: {{ my_text }}
{% endautoescape %}
{% autoescape off %}
    Not Escaped: {{ my_text }}
{% endautoescape %}
</pre>

如果my_text包含"Hello <b>world</b>",则呈现的内容将有两个版本的字符串:

autoescape 标签的示例呈现

autoescape on更改 HTML 特殊字符,使其呈现为字符串中的原样。相比之下,使用autoescape off,粗体标记会传递给浏览器。

所有使用特殊字符的语言都需要一种直接使用相同特殊字符的方法。如果要使用表示标签的字符,可以将它们包装在{% verbatim %}标签中:

{% verbatim %}
    Django uses mustaches braces to render variables: {{ is_scary }}.
{% endverbatim %}

许多JavaScript框架都有自己的模板语言。变量或标签的双括号格式很常见。如果您需要在 Django 模板中包含 JavaScript 模板,将它们包装在{% verbatim %}标签中将导致 Django 的模板渲染器忽略它们,将它们留在 JavaScript 中。

日期和时间

您经常需要在网站上显示日期和时间信息。{% now %}Django 模板语言中的标记为您提供当前日期和时间。它需要一个字符串参数来指定要显示的日期时间的格式。由于历史原因,格式字符串基于 PHPdate()函数而不是 Python 的strftime文档中提供了可能的格式字符列表。

{% now %}标签的一个常见用途是将当前年份显示为版权声明的一部分:

<p>Copyright 2012-{% now "Y" %}</p>

上面的示例将呈现从 2012 年到当前年份的版权声明。

网址

Django 的视图和路由机制有一种内置的 URL 命名方式。硬编码 URL 是不好的做法。如果有什么变化,那么你必须追查你在代码中使用它的所有时间。您可以使用{% url %}标记,而不是在视图中解析 URL 并将其作为上下文传递:

<a href="{% url 'home_page' filter %}">Home</a>

的参数{% url %}是任何URL 模式名称,与 Django 的reverse()工作方式相同。它可以选择将位置或命名参数用于所引用的基础视图。

探索关键模板过滤器

正如您之前学到的,Django 模板标签是模板语言的关键字和函数。过滤器就像是在 Django 渲染数据之前就地修改数据的小函数。

您可以通过|在变量后添加管道 ( ) 和过滤器名称将过滤器放在双括号内。这是受到在 Unix shell 中如何通过管道相互传递命令的启发。

现在,您将了解一些与字符串、列表、日期和时间一起使用的常见过滤器,以及展示如何使用它们的示例。

字符串过滤器

过滤器可以对各种数据进行操作。它们中的许多直接对应于具有相同目的的 Python 函数。该upper过滤器是一样的str.upper()在Python方法。使用它会将变量的内容更改为大写。通过修改templates/listing.htmlupper过滤器添加到movie.0变量中来尝试一下:

<!-- templates/listing.html -->
{% extends "base.html" %}

{% block content %}
  <h2> Movies</h2>
  <ul>
    <li>
       #{{forloop.counter}} {{movie.0|upper}} was released in {{movie.1}}
    </li>
⋮

通过上述更改,列表中的每个电影标题都将采用大写字母。毫不奇怪,还有一个相应的lower过滤器。

center过滤器添加填充到字符串的两侧。填充是一个空格字符,因此根据您的字体和包装它的标签,此过滤器的效果可能有限:

<pre>{{value}} becomes *{{ value|center:"16" }}*</pre>

如果valuecontains "Elephant",则此示例会在每侧产生四个空格:

<pre>Elephant becomes *    Elephant    *</pre>

如果需要从字符串中删除字符,可以使用cut过滤器。to 的参数cut是要删除的子字符串:

<pre>*{{value}}* becomes *{{ value|cut:" " }}*</pre>

看看当你使用cut带有valueof的过滤器时会发生什么"Bates Motel"

<pre>*Bates Motel* becomes *BatesMotel*</pre>

请注意, to 的参数cut不是要剪切的字符列表,而是要剪切的序列。如果你试图用它来减少这个值"ae",什么都不会发生。中没有"ae"子串"Bates Motel"

列出过滤器

过滤器可以对类似列表的值进行操作。在firstlast分别在迭代过滤器返回的第一项和最后一项,:

{{ goodies|first }}

如果goodies包含["popcorn", "peanuts", "cola"],则此示例的结果为"popcorn"。使用last过滤器会导致"cola".

除了使用过滤器访问列表的一部分之外,您还可以使用它们从列表中获取数据。该join滤波器类似于Python的str.join()方法。它返回一个由列表部分组成的字符串:

{{ goodies|join:", " }}

您可以使用冒号 ( :) 将参数传递给过滤器。goodies使用逗号作为参数加入列表会返回一个包含逗号分隔列表的字符串:"popcorn, peanuts, cola"

要查找列表的长度,请使用length过滤器。这在与其他过滤器结合使用时特别有用。当处理多个项目时,pluralize过滤器会"s"在单词的末尾添加一个。尝试将以下行添加到标题templates/listing.html正下方<h2>Movies</h2>

<!-- templates/listing.html -->
{% extends "base.html" %}

{% block content %}
  <h2> Movies</h2>
  <p>{{movies|length}} movie{{movies|length|pluralize}} found.</p>
  ⋮

Django 将第一组双括号替换为movies列表的长度。第二组正在做一些聪明的事情:链接过滤器。该pluralize过滤器采用一个数字。如果数字2大于或等于,则返回一个"s"。通过使用lengthand then pluralize,您将传递moviesto的长度pluralize

如果添加一个"s"不是您将单词复数的方式,您会怎么做?过滤器支持指定结束后缀的参数:

You have {{num_boxes}} box{{num_boxes|pluralize:"es"}}.

在这个例子中,而不是追加"s"pluralize追加"es",返回"boxes"。对于具有不同词尾的单词,您可以同时指定单数和复数词尾:

You have {{num_cherries}} cherr{{num_cherries|pluralize:"y,ies"}}.

在上面的示例中,pluralize如果结果是单数,则添加逗号前指定的字符串,如果结果是复数,则添加逗号后指定的字符串。这样,您就可以正确获得"cherry""cherries"

日期和时间过滤器

日期或时间的呈现应特定于用户的语言环境。在您的代码中,建议您仅使用 Pythondatetime对象。您应该将此对象的格式设置留给渲染时间。有过滤器可以帮助您解决这个问题。

date过滤器可以接受类似的参数{% now %},你看到在本教程前面的标签。与该标签一样,date过滤器的参数指定日期的表示格式:

<p> {{release_date|date:"Y-m-d"}}</p>

此示例将以release_date年-月-日ISO 8601格式显示 的内容。对于公民凯恩来说,这将是 1941-09-05(1941 年 9 月 5 日)的广泛发行。虽然它被称为date过滤器,但它也支持时间,假设它正在处理一个datetime对象而不仅仅是一个date对象。

如果您只对时间感兴趣,那么还有一个过滤器。的time过滤器使用的配置参数的子集date,只是那些具有时间做。用法类似:

<p> {{showing_at|time:"H:i"}}</p>

本示例以 24 小时时钟格式显示显示时间。对于晚上 9:30 的电影,Django 将其呈现为"21:30".

一种使时间更具可读性的流行格式是显示自事件以来经过的时间。您会在许多网络邮件客户端中看到这一点,这些客户端显示的信息类似于“3 天前”收到了一封电子邮件。Djangotimesince过滤器为您提供了这种能力:

<p> {{release_date|timesince}}</p>

此示例显示自电影发行日期以来经过的时间量。默认情况下,此过滤器计算从现在开始经过的时间。或者,您可以添加一个参数来timesince指定比较日期。

有一个配套过滤器timesince叫做timeuntil. 它不是向后看日期,而是向前看。您可以使用它来显示会议或类似事件的倒计时。

双方timesincetimeuntil根据服务器的时间计算差值时,Django的渲染模板。计算是使用 中的时区信息完成的settings.py。如果您的服务器不是 UTC 并且您的 Django 配置使用的是 UTC 默认值,这可能会产生奇怪的结果。确保这两个配置匹配,否则您的时差计算将不正确。

第三方标签和过滤器库

除了内置的 Django 模板标签和过滤器,您还可以编写自己的. 您可以找到有用的第三方库,其中包括自定义标签和过滤器。一个这样的库是django-simple-tags. 不要将其与simple_tag()Django 中类似命名的函数混淆。

要在模板中使用第三方库,您需要执行三个步骤:

  1. 安装应用程序库
  2. 注册与应用程序INSTALLED_APPSsettings.py
  3. 在模板中加载标签

安装 Django 应用程序库与任何其他包没有什么不同。您可以使用pip以下方法安装它:

$ python -m pip install django-simple-tags

安装软件包后,更新文件的INSTALLED_APPS一部分settings.py以使 Django 知道该应用程序:

33INSTALLED_APPS = [
34    "django.contrib.admin",
35    "django.contrib.auth",
36    "django.contrib.contenttypes",
37    "django.contrib.sessions",
38    "django.contrib.messages",
39    "django.contrib.staticfiles",
40    "core",
41    "django_simple_tags",
42]

现在 Django 知道该应用程序,但您还不能使用标签。在使用它们之前,首先需要将它们加载到模板中。您可以使用{% load %}标签执行此操作:

 1{% load django_simple_tags %}
 2
 3Current value of DEBUG is {% get_setting "DEBUG" %}

在第 1 行,{% load %}标签将所有标签添加django-simple-tags到您的模板上下文中。请注意,周围没有引号django_simple_tags。这要与import声明保持一致。该django-simple-tags库有二十多个标签和过滤器。此示例显示从 Django 设置{% get_setting %}返回的值DEBUG

有许多第三方库和大量可以简化 HTML 的标签。使用它们只是一个pip install和一个{% load %}标签。

结论

Django 模板标签和过滤器为您提供了一种以可重用方式构建 HTML 输出的强大方法。模板以它们自己的语言定义,以便将业务逻辑与显示逻辑分开。标签就像语言的关键字和功能,而过滤器允许您在显示之前修改现有数据。

在本教程中,您学习了如何:

  • 使用 DjangoTemplateContext对象编译模板
  • 从文件加载模板并使用render()快捷方式返回它们
  • 使用条件块循环块编写模板
  • 使用extendsinclude编写可重用的模板组件
  • 使用模板过滤器修改数据
  • 第三方库加载和使用自定义模板标签和过滤器

您可以在优秀文档 中找到有关 Django 的更多一般信息。在同一文档中,您还可以找到有关模板标签和过滤器的更多具体信息。

如果您想学习有关Real Python 的一些 Django 教程,您可以查看Django 入门第 1 部分:构建投资组合应用程序Django 的 Web 开发学习路径以及可用的Django 教程列表。

MoviePalace 教程中最后一个合适的词必须是:Rosebud

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。