Skip to content

模板层 Template

模板层的作用,是把后端数据渲染成用户能够看到的网页内容。

如果没有模板,你当然也可以在视图里直接拼 HTML 字符串,但那样会非常难维护。页面越复杂,代码就越混乱。

模板存在的意义就是:

  • 让 HTML 结构和 Python 逻辑分开
  • 让页面可以根据后端传来的数据动态变化

本节目标

  • 理解模板层的作用
  • 学会使用 render() 渲染页面
  • 理解上下文变量
  • 学会模板变量、条件、循环
  • 学会模板继承和复用
  • 学会使用常见过滤器
  • 建立“页面模板化”的基本意识

为什么需要模板

先看一种不推荐但很直观的写法:

python
from django.http import HttpResponse


def home(request):
    return HttpResponse("<h1>欢迎学习 Django</h1>")

这在极简单场景下能跑,但问题很明显:

  • HTML 写在 Python 字符串里,不好看
  • 页面一复杂就很难维护
  • 不能优雅复用页头、页脚、导航栏

所以正式开发里,通常会把页面写在模板文件里,再让 Django 把数据填进去。

最基础的模板渲染

视图:

python
from django.shortcuts import render


def home(request):
    return render(request, "home.html")

模板 home.html

html
<h1>欢迎来到 Python 学习空间</h1>
<p>这里是首页内容。</p>

访问这个页面后,浏览器看到的就是模板里的 HTML 结构。

render() 到底做了什么

python
render(request, "home.html")

你可以把它理解成:

  1. 找到模板文件
  2. 把模板渲染成最终 HTML
  3. 返回给浏览器

所以 render() 是 Django 模板层最常见的入口。

上下文变量是什么

很多时候,页面内容不是固定死的,而是来自后端数据。

例如:

  • 当前用户名
  • 文章标题
  • 课程列表
  • 搜索结果

这时就需要把数据从视图传给模板。

视图:

python
from django.shortcuts import render


def profile(request):
    context = {
        "name": "小明",
        "age": 18
    }
    return render(request, "profile.html", context)

模板:

html
<h1>{{ name }}</h1>
<p>年龄:{{ age }}</p>

页面最终显示:

text
小明
年龄:18

这里的 context 就是上下文数据。

模板变量

模板变量最常见的写法是:

html
{{ name }}

它表示:把视图传来的变量值显示到页面上。

字典取值

如果传来的数据是字典:

python
return render(request, "user.html", {
    "user": {
        "name": "小明",
        "city": "上海"
    }
})

模板可以这样写:

html
<p>{{ user.name }}</p>
<p>{{ user.city }}</p>

模板条件判断

模板中可以写简单逻辑。

html
{% if score >= 60 %}
  <p>及格</p>
{% else %}
  <p>不及格</p>
{% endif %}

如果 score80,页面显示:

text
及格

如果 score50,页面显示:

text
不及格

为什么模板里要有条件判断

因为页面展示经常要根据数据状态变化,例如:

  • 用户是否登录
  • 是否有搜索结果
  • 订单是否支付

模板循环

模板里经常要把列表数据一项一项渲染出来。

视图:

python
from django.shortcuts import render


def student_list(request):
    students = ["小明", "小红", "小刚"]
    return render(request, "student_list.html", {
        "students": students
    })

模板:

html
<h1>学员列表</h1>

{% for item in students %}
  <p>{{ item }}</p>
{% endfor %}

页面显示:

text
学员列表
小明
小红
小刚

模板里渲染表格

前面学循环时,你已经可以把列表逐条输出。现在看一个更实际的表格例子。

视图:

python
from django.shortcuts import render


def course_list(request):
    courses = [
        {"name": "Python 基础", "level": "入门"},
        {"name": "Django 开发", "level": "进阶"},
        {"name": "Scrapy 爬虫", "level": "进阶"}
    ]
    return render(request, "course_list.html", {
        "courses": courses
    })

模板:

html
<table border="1">
  <tr>
    <th>课程名称</th>
    <th>难度</th>
  </tr>

  {% for item in courses %}
    <tr>
      <td>{{ item.name }}</td>
      <td>{{ item.level }}</td>
    </tr>
  {% endfor %}
</table>

这样页面就能根据后端数据动态生成表格。

模板继承

这是模板层非常重要的能力。

为什么需要它?

因为一个网站通常很多页面都有共通部分,例如:

  • 页头
  • 导航栏
  • 页脚

如果每个页面都重复写,会非常低效。

父模板

base.html

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
  <h1>Python 学习空间</h1>
  <hr>

  {% block content %}
  {% endblock %}
</body>
</html>

子模板

home.html

html
{% extends "base.html" %}

{% block title %}首页{% endblock %}

{% block content %}
  <p>这里是首页内容。</p>
{% endblock %}

这样:

  • 公共结构只写一次
  • 子页面只关心自己不同的部分

这就是模板继承的核心意义。

模板包含

除了继承,你还可以拆出可复用小片段。

例如把导航栏单独写成:

nav.html

html
<nav>
  <a href="/">首页</a>
  <a href="/course/">课程</a>
</nav>

然后在其他模板中引入:

html
{% include "nav.html" %}

这也是模板复用的一种方式。

过滤器

过滤器可以在模板里对变量做一些简单处理。

大写

html
{{ name|upper }}

默认值

html
{{ nickname|default:"未设置昵称" }}

长度

html
{{ students|length }}

如果 students 列表有 3 项,页面就会显示:

text
3

过滤器的意义是:把一些简单展示处理放在模板层完成,而不是每次都在视图里先处理一遍。

模板标签和变量的区别

变量

用于输出数据:

html
{{ name }}

标签

用于控制逻辑:

html
{% if %}
{% for %}
{% block %}
{% include %}

简单记忆:

  • 负责显示内容
  • {% %} 负责控制逻辑

一个完整小案例:课程列表页

视图:

python
from django.shortcuts import render


def course_page(request):
    courses = [
        {"name": "Python 基础", "teacher": "张老师", "is_hot": True},
        {"name": "Linux 入门", "teacher": "李老师", "is_hot": False},
        {"name": "Django 开发", "teacher": "王老师", "is_hot": True},
    ]

    return render(request, "course_page.html", {
        "courses": courses
    })

模板:

html
<h1>课程列表</h1>

{% for item in courses %}
  <div>
    <h3>{{ item.name }}</h3>
    <p>讲师:{{ item.teacher }}</p>

    {% if item.is_hot %}
      <p>状态:热门课程</p>
    {% else %}
      <p>状态:普通课程</p>
    {% endif %}
  </div>
  <hr>
{% endfor %}

这个例子已经把模板最常见的三个能力串起来了:

  • 变量输出
  • 循环
  • 条件判断

常见错误

1. 变量名传错

视图里传的是:

python
{"name": "小明"}

模板里却写:

html
{{ username }}

那页面当然取不到值。

2. 模板标签没闭合

例如:

html
{% if score > 60 %}
  <p>及格</p>

少了:

html
{% endif %}

3. 把复杂业务逻辑硬塞进模板

模板应该负责展示,不应该承担太复杂的数据处理逻辑。复杂逻辑应尽量留在视图或模型层。

4. 父模板和子模板的 block 对不上

如果父模板定义的是:

html
{% block content %}{% endblock %}

子模板却写成别的名字,就不会生效。

练习题

练习 1

写一个模板页面,显示你的昵称和学习方向。

练习 2

传一个学员列表到模板中,用循环逐项输出。

练习 3

传一个成绩到模板里,用条件语句判断“及格”或“不及格”。

练习 4

写一个父模板 base.html,再写一个子模板 home.html 继承它。

练习 5

尝试使用 upperdefaultlength 这几个过滤器做简单练习。

本节小结

模板层的核心意义,是把页面结构和 Python 逻辑分开,并让页面能够根据后端数据动态变化。

你这一节最重要的收获应该是:

  • 会用 render() 返回模板页面
  • 理解上下文变量
  • 会用变量、条件和循环渲染页面
  • 理解模板继承和复用
  • 会用简单过滤器处理显示效果

只要模板这一层打牢,后面你做 Django 页面就不再只是“返回字符串”,而是真正开始做网站页面。

Built with VitePress.