Django 模板语言

环境信息

  • Python 3.11
  • Django 4.1

使用方法

在 Django 4.1 中,使用静态文件的方法与之前的版本相同。以下是使用静态文件的步骤:

  1. settings.py 中设置静态文件目录:

    settings.py
    STATIC_URL = '/static/'
    STATICFILES_DIRS = [
    BASE_DIR / "static",
    ]
    • STATIC_URL 是静态文件 URL 的前缀。
    • STATICFILES_DIRS 是一个列表,其中包含要在其中查找静态文件的目录。
  2. 在 HTML 文件中使用静态文件

    {% load static %}
    <!DOCTYPE html>
    <html>
    <head>
    <title>My Static File Example</title>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
    </head>
    <body>
    <img src="{% static 'images/logo.png' %}" alt="My logo">
    <script src="{% static 'js/script.js' %}"></script>
    </body>
    </html>

    在上面的示例中,我们使用了 Django 模板语言的 {% static %} 标记来引用静态文件。{% load static %} 指令必须在使用 {% static %} 标记之前加载,以确保 Django 能够正确解析它们。

  3. 运行 collectstatic 命令:
    当您准备部署您的 Django 应用程序时,您需要将静态文件收集到一个单独的目录中,以便可以轻松地在生产服务器上提供它们。您可以使用 Django 的 collectstatic 命令来完成此操作。在命令行中运行以下命令:

    python manage.py collectstatic

    Django 将在 STATIC_ROOT 目录中创建一个新的静态文件目录,并将您的静态文件从 STATICFILES_DIRS 中指定的目录复制到该目录中。您可以在 settings.py 文件中设置 STATIC_ROOT 目录的路径

DTL 语法

load static

参考说明

block.super

用来从父 block 中继承选项

{% load static %}

{% block extrahead %}
{{ block.super }}
<link href="{% static 'bootstrap/css/bootstrap.css' %}" rel="stylesheet" />
<link href="{% static 'bootstrap/css/base.css' %}" rel="stylesheet" />
{% endblock %}

include

假设有两个 HTML 文件:header.htmlcontent.html
header.html 包含页面的头部内容。

header.html
<!-- header.html -->
<header>
<h1>My Website</h1>
<nav>
<!-- 导航栏内容 -->
</nav>
</header>

content.html 包含页面的主要内容。

content.html
<!-- content.html -->
<section>
<h2>Welcome to our website!</h2>
<p>This is the main content of the page.</p>
</section>

现在,可以在另一个 HTML 文件中使用 {% include %} 标签来包含这些内容。

main_template.html
<!-- main_template.html -->
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
{% include 'header.html' %}

<div class="content">
{% include 'content.html' %}
</div>

<footer>
<!-- 页脚内容 -->
</footer>
</body>
</html>

在这个示例中,{% include 'header.html' %}{% include 'content.html' %} 标签会将相应的模板文件的内容包含在 main_template.html 中。这样,就可以在一个模板中包含另一个模板的内容了。

url 反向解析

在模板中不推荐使用 url 硬编码,建议使用 url 反向解析功能,在 urls.py 中定义 url 时,给 url 命名,在模板中 可以使用反向解析使用 url,避免使用 url 硬编码。需要在 urls.py 中配置 app_name = 'polls',否则会因为 namespace 不清楚而报错:'polls' is not a registered namespace

from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]

以上事例中,name='index' 为 url 命名,在模板中通过以下方式使用 url 名称 [1]

<a href="{% url 'polls:index' %}">首页</a>

for 循环

根据 model 中的值实现下拉选择菜单

假如需要实现下拉表单中的可选值来自于某个 model,可以参考以下实现

models.py
from django.db import models

# Create your models here.
class Account(models.Model):
name = models.CharField(max_length=16, unique=True)

视图函数代码如下:

views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from cloudclient import models

# Create your views here.


@login_required
def index(request):
accounts = models.Account.objects.all()
return render(request, 'index.html', {'accounts': accounts})

HTML 模板主要代码如下:

index.html
<form method="POST">
{% csrf_token %}
<label for="category">Select An Account: </label>
<select name="account" id="account">
{% for account in accounts %}
<option value="{{ account.id }}">{{ account.name }}</option>
{% endfor %}
</select>
<button type="submit">Submit</button>
</form>

其中使用 for 循环将视图函数传过来的参数列表(accounts)中的对象添加到下拉菜单中作为下拉选项。

表单提交后,服务端口会收到 POST 的数据(request.POST):account=1。参考以下代码处理接收到的表单数据

views.py
@login_required
def index(request):
if request.method == 'GET':
accounts = models.Account.objects.all()
return render(request, 'index.html', {'accounts': accounts})
if request.method == 'POST':
# data = request.body
account_id = request.POST.get('account')
logging.info(f"POST DATA: {}")

如果想在 POST 处理后返回给客户端的 HTML 表单中的默认选中的值任然是客户端 POST 提交时选中的值,可以参考以下代码

views.py
@login_required
def cf_add_domains(request):
accounts = models.Account.objects.all()
if request.method == 'POST':
data = request.POST
account_id = data['account']
account = models.Account.objects.get(id=account_id)

return render(request, 'index.html', {'accounts': accounts, 'selected_account_id': account_id})

HTML 模板中使用 optionselected 标签选择指定的值。要注意其中的类型转换 account.id|stringformat:"s" == selected_account_id|stringformat:"s",将变量值转换一致,否则条件判断会失败

index.html
<form method="POST">
{% csrf_token %}
<label for="account">Select An Account: </label>
<select name="account" id="account">

{% for account in accounts %}
{% if account.id|stringformat:"s" == selected_account_id|stringformat:"s" %}
<option value="{{ account.id }}" selected>{{ account.name }}</option>
{% else %}
<option value="{{ account.id }}">{{ account.name }}-{{ account.id }}-{{ selected_account_id }}</option>
{% endif %}
{% endfor %}
</select>
<button type="submit">Submit</button>
</form>

if 条件判断

if 语法如下

{% if condition %}
<!-- 显示内容如果条件为真 -->
{% else %}
<!-- 显示内容如果条件为假 -->
{% endif %}

{% if user.is_authenticated %}
<p>欢迎回来,{{ user.username }}!</p>
<a href="{% url 'logout' %}">退出登录</a>
{% else %}
<p>您还未登录。</p>
<a href="{% url 'login' %}">立即登录</a>
{% endif %}

类型转换

如果在模板中需要对变量类型进行转换,参考以下语法

{% for account in accounts %}
{% if account.id|stringformat:"s" == selected_account_id|stringformat:"s" %}
<option value="{{ account.id }}" selected>{{ account.name }}</option>
{% else %}
<option value="{{ account.id }}">{{ account.name }}-{{ account.id }}-{{ selected_account_id }}</option>
{% endif %}
{% endfor %}

更精简的写法

{% for account in accounts %}

<option value="{{ account.id }}" {% if account.id|stringformat:"s" == selected_account_id|stringformat:"s" %}selected{% endif %}>{{ account.name }}</option>
{% endfor %}

脚注