Django 模板:让前端与后端“心有灵犀”
你有没有遇到过这样的场景?写完一个功能,数据能跑通,但页面却像一张白纸,或者格式乱七八糟?这背后,往往是因为你还没掌握 Django 模板系统。它就像是 Django 的“视觉中枢”——负责把数据变成用户看得懂、用得顺的网页。
Django 模板不是简单的 HTML 文件拼接,而是一套逻辑清晰、功能强大的动态渲染机制。它让你既能保持 HTML 的结构美感,又能灵活注入 Python 逻辑,真正实现“前后端分离”的优雅协作。今天,我们就从零开始,带你一步步掌握 Django 模板的核心能力。
什么是 Django 模板?
Django 模板是一种基于文本的模板引擎,专门用于生成 HTML、XML 或其他文本格式。你可以把它想象成一个“网页工厂”:你提供“模具”(模板文件),再塞入“原材料”(数据),它就自动输出完整的网页。
它的核心价值在于:将业务逻辑与页面展示逻辑分离。开发者专注写代码,设计师专注做 UI,互不干扰,协作更高效。
在 Django 中,模板文件通常以 .html 为扩展名,放在项目目录下的 templates 文件夹中。Django 会自动加载这些文件,并根据视图函数传递的数据进行动态渲染。
创建模板文件与基本结构
要使用 Django 模板,第一步是创建模板文件。假设你有一个博客项目,想展示一篇标题为“Django 入门指南”的文章。
首先,在你的应用目录中创建 templates 文件夹,比如 blog/templates/blog/,然后新建一个文件:article.html。
<!-- article.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ article_title }}</title>
</head>
<body>
<h1>{{ article_title }}</h1>
<p>作者:{{ author_name }}</p>
<div class="content">
{{ article_content }}
</div>
</body>
</html>
注释:
{{ article_title }}是一个变量占位符,Django 会在渲染时替换为实际值。{{ author_name }}和{{ article_content }}同理。<!DOCTYPE html>声明文档类型,确保浏览器正确解析。<title>标签中的{{ article_title }}会动态更新页面标题,非常实用。
这个模板现在还不能直接用,必须在视图中加载并传递数据。
在视图中使用模板:render 函数
Django 提供了 render 函数,用于将模板与数据结合,返回一个 HTTP 响应。
from django.shortcuts import render
def show_article(request):
# 准备要传给模板的数据
context = {
'article_title': 'Django 模板入门指南',
'author_name': '小明',
'article_content': 'Django 模板是构建动态网页的核心工具。它支持变量、标签和过滤器,让开发者轻松控制页面输出。'
}
# 使用 render 函数渲染模板,并返回响应
return render(request, 'blog/article.html', context)
注释:
render(request, template_name, context)是 Django 提供的标准函数。request是 HTTP 请求对象,必须传入。template_name是模板文件的路径,从templates根目录开始写,用斜杠分隔。context是一个字典,包含所有要传递给模板的数据。- 调用后,Django 会自动查找模板文件,替换变量,返回完整 HTML 响应。
现在访问对应 URL,就能看到动态生成的网页了。
模板标签:控制流程的“指挥棒”
变量只是基础,真正让 Django 模板强大的是标签(Tags)。它们就像编程中的 if-else、for 循环,能控制模板的执行流程。
使用 if 标签实现条件渲染
比如你想根据文章状态显示“已发布”或“草稿”标签:
<!-- 在 article.html 中添加 -->
{% if is_published %}
<span class="status published">已发布</span>
{% else %}
<span class="status draft">草稿</span>
{% endif %}
注释:
{% if ... %}和{% endif %}构成一个条件块。is_published是布尔值,True 显示“已发布”,False 显示“草稿”。- 模板中不支持复杂的逻辑判断,仅支持简单比较(如
==、!=),适合展示场景。
使用 for 标签遍历列表
假设你想展示文章的多个标签:
<!-- 在 article.html 中添加 -->
<ul class="tags">
{% for tag in tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
注释:
for标签用于遍历可迭代对象(如列表、元组)。tag是当前循环的变量名,可自定义。- 每次循环输出一个
<li>,最终生成标签列表。endfor必须闭合,否则模板渲染会出错。
模板过滤器:美化数据的“化妆师”
变量传进去了,但格式可能不够理想。比如时间显示为 2024-04-05 14:30:22,用户更希望看到“2024年4月5日 14:30”。这时,过滤器就派上用场了。
Django 内置了丰富的过滤器,语法是:{{ value|filter_name:argument }}
常用过滤器示例
<!-- 显示发布时间 -->
<p>发布时间:{{ publish_time|date:"Y年m月d日 H:i" }}</p>
<!-- 转换为大写 -->
<p>标题:{{ article_title|upper }}</p>
<!-- 截取字符串 -->
<p>摘要:{{ article_content|truncatewords:10 }}</p>
<!-- 安全转义 HTML(防止 XSS) -->
<div>{{ user_input|safe }}</div>
注释:
date过滤器支持多种格式,"Y年m月d日 H:i"会输出“2024年04月05日 14:30”。upper将字符串转为大写。truncatewords截取前 10 个单词,适合摘要。safe表示内容可信,允许 HTML 渲染,但需谨慎使用,避免安全风险。
模板继承:打造统一的网站结构
如果你有多个页面(如首页、文章页、关于页),每个页面都有相同的头部、导航栏、页脚,重复写 HTML 会非常低效。
Django 提供了模板继承机制,让你只需定义一个“母版”模板,其他页面继承它,只需覆盖特定区域。
创建基础模板 base.html
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}我的 Django 网站{% endblock %}</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<!-- 顶部导航 -->
<header>
<nav>
<a href="/">首页</a>
<a href="/about/">关于</a>
<a href="/blog/">博客</a>
</nav>
</header>
<!-- 主要内容区域 -->
<main>
{% block content %}
<!-- 子模板可覆盖此区域 -->
{% endblock %}
</main>
<!-- 页脚 -->
<footer>
© 2024 我的网站. 保留所有权利。
</footer>
</body>
</html>
注释:
{% block title %}和{% block content %}是“占位块”,子模板可覆盖。block与endblock成对出现,定义可替换区域。title块默认值为“我的 Django 网站”,子模板可改写。
继承基础模板的子模板
<!-- templates/blog/article.html -->
{% extends 'base.html' %}
{% block title %}Django 模板详解{% endblock %}
{% block content %}
<h1>{{ article_title }}</h1>
<p>作者:{{ author_name }}</p>
<div class="article-content">
{{ article_content|linebreaks }}
</div>
{% endblock %}
注释:
{% extends 'base.html' %}表示继承base.html。block title和block content会覆盖父模板中的对应块。linebreaks过滤器将换行符转为<br>,适合纯文本内容。
实际案例:搭建一个简单博客列表页
我们来实战一个完整案例:展示多篇文章列表。
视图函数
from django.shortcuts import render
def article_list(request):
articles = [
{
'title': 'Django 模板入门',
'author': '小明',
'date': '2024-04-05',
'tags': ['Django', '模板', 'Python'],
'published': True
},
{
'title': 'REST API 设计',
'author': '小红',
'date': '2024-04-03',
'tags': ['API', 'JSON'],
'published': False
}
]
return render(request, 'blog/list.html', {'articles': articles})
模板文件 list.html
{% extends 'base.html' %}
{% block title %}文章列表{% endblock %}
{% block content %}
<h2>最新文章</h2>
<ul class="article-list">
{% for article in articles %}
<li class="article-item">
<h3><a href="/article/{{ forloop.counter }}/">{{ article.title }}</a></h3>
<p>作者:{{ article.author }} | 发布时间:{{ article.date|date:"Y年m月d日" }}</p>
{% if article.published %}
<span class="status published">已发布</span>
{% else %}
<span class="status draft">草稿</span>
{% endif %}
<ul class="tags">
{% for tag in article.tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
{% endblock %}
注释:
forloop.counter是循环索引,从 1 开始。- 通过
forloop可访问循环状态,如counter,first,last。- 模板结构清晰,逻辑分明,易于维护。
总结:Django 模板让开发更高效
Django 模板不是“可有可无”的功能,而是 Django 架构中不可或缺的一环。它通过变量、标签、过滤器和继承机制,实现了动态内容渲染与结构复用的完美平衡。
从简单的变量替换,到复杂的条件判断与循环遍历,再到跨页面的结构统一,Django 模板让你既能快速搭建原型,也能构建可维护的中大型项目。
掌握它,意味着你真正迈入了 Django 的“全栈”世界。别再把 HTML 当作静态文件,把它当作一个“可编程的界面”,你会发现,前后端协作,原来可以如此顺畅。