模板继承与安全输出
学习目标
将 HTML 从视图移到模板,用继承复用页头页脚,用上下文字典传递数据,理解自动转义为何不能随意关闭。
为什么让视图和模板分工
视图负责“取什么数据、是否允许访问”,模板负责“怎样显示”。把 HTML 拼在 Python 字符串中会让条件、链接和页面结构越来越难维护。render(request, 模板名, 上下文) 会加载模板并返回 HTML 响应。
base.html 定义公共骨架,子模板通过 extends 继承,通过 block 替换页面标题和正文。模板语言不是完整 Python:尽量在视图中计算数据,只在模板中做展示判断。这个分工与本站 templates/base.html、templates/course/show.html 一致。
具体怎么做
- 在根目录建立
templates/,其中blog/存放博客页面。 - 替换视图,使首页传入
greeting。字典键greeting对应模板里的{{ greeting }}。 - 基础模板使用
{% url %},避免导航地址散落在各页。 - 加入
lang、字符集、viewport 和“跳到正文”链接,开始建立可访问的页面结构。
本章新增或替换的完整文件
以下路径均相对于练习项目根目录。替换同名文件的全部内容;未列出的文件保持上一章版本。
blog/views.py
from django.shortcuts import render, redirect
from django.views.decorators.http import require_GET
@require_GET
def home(request):
return render(request, "blog/home.html", {"greeting": "欢迎来到知行博客"})
@require_GET
def about(request):
return render(request, "blog/about.html")
@require_GET
def old_home(request):
return redirect("blog:home")
templates/base.html
<!doctype html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}知行博客{% endblock %}</title></head>
<body>
<a href="#main">跳到正文</a>
<header><nav aria-label="主导航"><a href="{% url 'blog:home' %}">知行博客</a> <a href="{% url 'blog:about' %}">关于</a></nav></header>
<main id="main">{% block content %}{% endblock %}</main>
<footer>知行博客 · 记录、实践、分享</footer>
</body></html>
templates/blog/about.html
{% extends "base.html" %}
{% block title %}关于 · 知行博客{% endblock %}
{% block content %}<h1>关于知行博客</h1><p>这是贯穿教程的博客项目,支持阅读、写作和讨论。</p>{% endblock %}
templates/blog/home.html
{% extends "base.html" %}
{% block content %}<h1>{{ greeting }}</h1><p>今天开始,把学习变成可以运行的代码。</p>{% endblock %}
如何确认成功
python manage.py check
python manage.py runserver
首页显示“欢迎来到知行博客”,关于页有独立的浏览器标题,但页头和页脚相同。按 Tab 键,应能用键盘走到导航链接。
在 shell 中做一个不修改文件的安全实验:
python manage.py shell -c "from django.template.loader import render_to_string; print(render_to_string('blog/home.html', {'greeting': '<script>alert(1)</script>'}))"
输出中危险字符串应变成 <script>,不会被当成脚本执行。以后文章正文默认以纯文本保存并转义展示;只有经过可信清洗的 HTML 才能使用 safe。本站的教程内容会经过现有 HTML 清洗器,和练习项目的纯文本文章是两个不同场景。
练习:为关于页添加一个新的 block 或一段说明,验证没有复制整份 HTML。再尝试拼错模板路径,阅读 TemplateDoesNotExist 错误展示的搜索位置。
常见问题
变量不显示也不报错? 模板中的不存在变量通常显示为空,先核对上下文键名。extends 放在哪里? 子模板中它应是第一个模板标签,避免继承行为不明确。为什么不用 safe 解决换行? safe 会改变安全边界,换行请用后面的 linebreaks 过滤器,它会处理转义和段落。
官方参考
登录后可保存阅读位置、标记章节完成,并在其他设备继续学习。
登录并保存学习进度 →联系站长
微信:VIPdjango。技术问题建议先在 社区讨论 中交流,方便更多人参与和查阅。
章节讨论 0