青少年编程与数学 02-009 Django 5 Web 编程 11课题、模板系统
- 一、模板
-
-
- [1. 模板的基本概念](#1. 模板的基本概念)
- [2. 模板的加载和渲染](#2. 模板的加载和渲染)
- [3. 模板继承](#3. 模板继承)
- [4. 自定义模板标签和过滤器](#4. 自定义模板标签和过滤器)
- [5. 模板的配置和优化](#5. 模板的配置和优化)
-
- 二、模板标签
- 三、模板过滤器
- 四、模板配置
- 五、练习
课题摘要: 本文深入解析了Django的模板系统,涵盖模板的基本概念、加载与渲染、继承、自定义标签和过滤器,以及模板配置。模板是包含静态和动态内容的文本文件,通过标签和变量实现动态插入。上下文是传递给模板的数据字典,而模板标签和过滤器分别用于控制逻辑和格式化变量。文章介绍了如何通过
render()
函数结合模板和上下文生成HTML内容,以及如何利用模板继承和块标签简化页面结构。此外,还讲解了自定义模板标签和过滤器的创建方法,以及如何在settings.py
中配置模板引擎的选项,如模板目录和调试模式。最后,通过一个博客应用示例,展示了模板系统的实际应用,包括基础模板、列表页面和详情页面的创建和配置。
一、模板
Django的模板系统是一个强大的工具,用于将数据动态地插入到HTML页面中。它允许开发者将业务逻辑与展示逻辑分离,使得前端页面的开发更加灵活和高效。以下是Django模板系统的详细解析:
1. 模板的基本概念
- 模板 (Template):一个文本文件,通常是一个HTML文件,包含用于展示的静态内容和动态内容的占位符。动态内容通过模板标签和变量来实现.
- 上下文 (Context):一个字典,包含了模板中需要使用的变量和数据。在视图中创建上下文,并将其传递给模板进行渲染.
- 模板标签 (Template Tags) :用于在模板中插入动态内容或控制模板的逻辑流程。例如,
{% for %}
用于循环,{% if %}
用于条件判断. - 模板过滤器 (Template Filters) :用于对变量的值进行格式化或处理。例如,
|upper
将变量的值转换为大写,|date:"Y-m-d"
将日期格式化为指定格式.
2. 模板的加载和渲染
-
加载模板 :Django通过模板加载器来加载模板文件。默认情况下,Django会从
settings.py
文件中配置的TEMPLATES
设置的DIRS
选项指定的目录中查找模板文件. -
渲染模板 :在视图中,使用
render()
函数将模板和上下文结合起来,生成最终的HTML内容。例如:pythonfrom django.shortcuts import render def my_view(request): context = {'message': 'Hello, Django!'} return render(request, 'my_template.html', context)
在这个例子中,
my_template.html
是模板文件,context
是上下文字典,render()
函数将上下文中的变量message
插入到模板中,生成最终的HTML页面.
3. 模板继承
-
模板继承:Django模板系统支持模板继承,允许创建一个基础模板,其他模板可以继承它并重写其中的部分内容。基础模板通常包含页面的公共结构,如头部、尾部、导航栏等.
-
块标签 (block tag) :在基础模板中,使用
{% block %}
标签定义可以被子模板重写的内容块。子模板通过{% extends %}
标签继承基础模板,并使用{% block %}
标签重写相应的内容块.html<!-- base.html --> <html> <head> <title>{% block title %}My Site{% endblock %}</title> </head> <body> {% block content %} {% endblock %} </body> </html>
html<!-- child.html --> {% extends "base.html" %} {% block title %}Child Page{% endblock %} {% block content %} <p>This is the content of the child page.</p> {% endblock %}
4. 自定义模板标签和过滤器
- 自定义模板标签:可以通过编写Python代码来创建自定义的模板标签,实现特定的功能。自定义标签可以是简单的标签,也可以是包含块的标签.
- 自定义模板过滤器:可以编写自定义的过滤器来对变量的值进行处理。自定义过滤器需要在Python代码中定义,并在模板中注册后才能使用.
5. 模板的配置和优化
- 模板配置 :在
settings.py
文件中,可以通过TEMPLATES
设置来配置模板引擎的选项,如模板目录、模板后缀、模板缓存等. - 模板缓存:为了提高性能,可以开启模板缓存功能,使得模板文件在第一次加载后被缓存起来,后续请求可以直接使用缓存的模板,减少文件读取和解析的时间.
Django的模板系统提供了丰富的功能和灵活的扩展性,使得开发者能够高效地开发出动态的Web页面,同时保持代码的清晰和可维护性.
二、模板标签
Django的模板标签(Template Tags)是模板系统中用于插入动态内容和控制模板逻辑的工具。模板标签可以执行各种操作,如循环、条件判断、加载模板片段等。以下是对Django模板标签的详细解析:
基本用法
- 语法 :模板标签使用花括号和百分号包围,例如
{% tag %}
. - 位置:模板标签通常放在HTML代码中需要动态插入内容或控制逻辑的地方.
常用模板标签
控制流标签
-
if/elif/else :用于条件判断.
html{% if user.is_authenticated %} <p>Welcome, {{ user.username }}!</p> {% elif user.is_anonymous %} <p>Please log in.</p> {% else %} <p>Unknown user status.</p> {% endif %}
-
for :用于循环遍历可迭代对象,如列表、字典等.
html<ul> {% for item in items %} <li>{{ item.name }}</li> {% endfor %} </ul>
- 循环变量 :在
for
循环中,可以使用一些特殊的变量,如forloop.counter
(当前循环的索引,从1开始)、forloop.last
(判断是否是最后一个元素)等.
- 循环变量 :在
-
with :用于在模板中创建一个临时变量,简化模板的复杂度.
html{% with total=items|length %} <p>Total items: {{ total }}</p> {% endwith %}
模板加载标签
-
extends :用于模板继承,指定当前模板继承的基础模板.
html{% extends "base.html" %}
-
block :在继承的模板中定义可以被子模板重写的内容块.
html{% block content %} <p>This is the default content.</p> {% endblock %}
-
include :用于在模板中包含另一个模板片段,可以传递变量.
html{% include "header.html" with title="My Page" %}
模板控制标签
-
load :用于加载自定义的模板标签库,使得自定义标签可以在模板中使用.
html{% load my_custom_tags %}
-
spaceless :用于移除HTML标签之间的空白字符,减少页面大小.
html{% spaceless %} <div> <p>Hello, World!</p> </div> {% endspaceless %}
-
autoescape :用于控制自动转义的开启和关闭,防止XSS攻击.
html{% autoescape off %} <p>{{ user_input }}</p> {% endautoescape %}
自定义模板标签
-
简单标签(Simple Tag) :用于执行一些简单的操作,并返回一个字符串结果.
pythonfrom django import template register = template.Library() @register.simple_tag def multiply(x, y): return x * y
在模板中使用:
html{% load my_custom_tags %} <p>{{ 3|multiply:4 }}</p>
-
包含标签(Inclusion Tag) :用于渲染一个模板片段,并将结果插入到当前模板中.
python@register.inclusion_tag('my_template.html') def show_items(items): return {'items': items}
在模板中使用:
html{% load my_custom_tags %} {% show_items items %}
-
块标签(Block Tag) :用于创建复杂的模板标签,可以包含其他模板标签和变量.
python@register.tag(name='my_block_tag') def do_my_block_tag(parser, token): nodelist = parser.parse(('end_my_block_tag',)) parser.delete_first_token() return MyBlockNode(nodelist) class MyBlockNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist def render(self, context): output = self.nodelist.render(context) return '<div>' + output + '</div>'
在模板中使用:
html{% load my_custom_tags %} {% my_block_tag %} <p>Hello, World!</p> {% end_my_block_tag %}
Django的模板标签提供了丰富的功能,使得模板的开发更加灵活和高效。通过合理使用模板标签,可以有效地控制模板的逻辑和结构,实现动态内容的展示.
三、模板过滤器
Django的模板过滤器(Template Filters)是用于对模板中的变量值进行处理和格式化的工具。过滤器可以对变量进行各种操作,如字符串处理、日期格式化、列表操作等。以下是对Django模板过滤器的详细解析:
基本用法
- 语法 :过滤器使用管道符号(
|
)连接变量和过滤器名称,例如{``{ variable|filter }}
。 - 链式使用 :可以将多个过滤器串联使用,对变量进行多重处理,例如
{``{ variable|filter1|filter2 }}
。
内置过滤器
Django提供了许多内置的过滤器,以下是一些常用的内置过滤器:
字符串过滤器
-
safe
:标记变量为安全的,不会自动转义HTML内容。html{{ my_html_variable|safe }}
-
escape
:对变量进行HTML转义,防止XSS攻击。html{{ user_input|escape }}
-
lower
:将字符串转换为小写。html{{ "Hello, World!"|lower }}
-
upper
:将字符串转换为大写。html{{ "Hello, World!"|upper }}
-
capitalize
:将字符串的首字母大写,其余字母小写。html{{ "hello, world!"|capitalize }}
-
slugify
:将字符串转换为URL友好的格式(slug),只包含字母、数字、下划线和连字符。html{{ "Hello, World!"|slugify }}
-
truncatechars
:截取字符串,保留指定数量的字符。html{{ "Hello, World!"|truncatechars:5 }}
-
join
:将列表中的元素连接成字符串,使用指定的分隔符。html{{ my_list|join:", " }}
日期和时间过滤器
-
date
:将日期对象格式化为指定的格式。html{{ my_date|date:"Y-m-d" }}
-
time
:将时间对象格式化为指定的格式。html{{ my_time|time:"H:i:s" }}
-
timesince
:显示距离指定日期或时间的相对时间。html{{ my_date|timesince }}
-
timeuntil
:显示距离指定日期或时间的剩余时间。html{{ my_date|timeuntil }}
列表过滤器
-
first
:获取列表的第一个元素。html{{ my_list|first }}
-
last
:获取列表的最后一个元素。html{{ my_list|last }}
-
length
:获取列表的长度。html{{ my_list|length }}
-
slice
:对列表进行切片操作。html{{ my_list|slice:"1:3" }}
自定义过滤器
-
定义过滤器 :在Django应用的
templatetags
目录下的Python文件中定义过滤器。首先需要创建一个templatetags
目录,并在其中创建一个Python文件(例如my_custom_filters.py
),然后编写过滤器代码。pythonfrom django import template register = template.Library() @register.filter def add_prefix(value, prefix): return f"{prefix}{value}"
-
加载过滤器 :在模板中使用
{% load %}
标签加载自定义过滤器库。html{% load my_custom_filters %}
-
使用过滤器 :在模板中使用自定义过滤器。
html{{ my_variable|add_prefix:"Prefix: " }}
过滤器的注意事项
- 安全性 :在使用过滤器时,需要注意安全性问题,特别是涉及到HTML内容的过滤器。例如,当使用
safe
过滤器时,要确保变量的内容是安全的,不会导致XSS攻击. - 性能:过滤器的执行会影响模板的渲染性能,尤其是在处理大量数据或复杂逻辑时。应尽量使用内置过滤器,避免过多的自定义过滤器,以提高模板的渲染效率.
- 可读性:在模板中过度使用过滤器可能导致代码的可读性降低。应合理使用过滤器,保持模板的简洁和清晰.
Django的模板过滤器提供了丰富的功能,使得模板中的变量处理和格式化更加灵活和方便。通过合理使用内置过滤器和自定义过滤器,可以有效地实现模板中的数据展示需求.
四、模板配置
在Django中,模板配置主要通过项目的settings.py
文件中的TEMPLATES
设置来完成。TEMPLATES
是一个列表,其中每个元素都是一个字典,用于配置一个模板引擎。以下是如何进行模板配置的详细步骤和选项:
基本配置
默认情况下,Django已经提供了一个基本的模板配置,通常位于settings.py
文件中:
python
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
# Some options here
},
},
]
配置选项详解
BACKEND
- 作用 :指定模板引擎的后端。Django默认使用
django.template.backends.django.DjangoTemplates
,这是Django自带的模板引擎. - 可选值:除了默认的Django模板引擎,还可以使用其他模板引擎,如Jinja2等.
DIRS
-
作用 :指定模板文件的搜索目录。Django会按照
DIRS
列表中的顺序查找模板文件. -
示例 :
python'DIRS': [os.path.join(BASE_DIR, 'templates')],
这里将项目的
templates
目录添加到模板搜索路径中.
APP_DIRS
- 作用 :指示Django是否在每个应用的
templates
子目录中查找模板文件。如果设置为True
,Django会在每个应用的templates
目录中自动查找模板文件. - 默认值 :
True
OPTIONS
- 作用 :用于配置模板引擎的其他选项。以下是一些常用的选项:
-
context_processors
:上下文处理器列表,用于自动添加变量到模板的上下文中。例如,可以添加请求对象、用户对象等.python'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }
-
loaders
:模板加载器列表,用于指定如何加载模板文件。默认情况下,Django使用文件系统加载器和应用目录加载器.python'OPTIONS': { 'loaders': [ 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ], }
-
debug
:模板调试模式,如果设置为True
,在模板渲染出错时会显示详细的调试信息.python'OPTIONS': { 'debug': True, }
-
string_if_invalid
:无效变量的默认值,用于在模板中访问不存在的变量时返回一个指定的字符串.python'OPTIONS': { 'string_if_invalid': 'Invalid Variable', }
-
多模板引擎配置
如果需要在同一个项目中使用多个模板引擎,可以在TEMPLATES
列表中添加多个配置字典。例如,同时使用Django模板和Jinja2模板:
python
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'django_templates')],
'APP_DIRS': True,
'OPTIONS': {
# Django template options
},
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [os.path.join(BASE_DIR, 'jinja2_templates')],
'APP_DIRS': False,
'OPTIONS': {
'environment': 'myapp.jinja2.environment',
},
},
]
在这个示例中,Django模板和Jinja2模板分别配置了不同的模板目录和选项.
通过合理配置TEMPLATES
设置,可以满足不同项目的需求,实现高效的模板管理和渲染.
五、练习
以下是一个简单的Django应用模板示例项目,该项目包含一个简单的博客应用,具有文章列表和文章详情页面的功能:
项目结构
myblog/
manage.py
myblog/
__init__.py
settings.py
urls.py
wsgi.py
blog/
__init__.py
admin.py
apps.py
models.py
tests.py
urls.py
views.py
templates/
blog/
base.html
index.html
detail.html
创建项目和应用
-
创建Django项目:
bashdjango-admin startproject myblog
-
进入项目目录:
bashcd myblog
-
创建应用:
bashpython manage.py startapp blog
配置项目
-
在
myblog/settings.py
中添加应用到INSTALLED_APPS
:pythonINSTALLED_APPS = [ # ... 'blog', ]
-
在
myblog/urls.py
中包含应用的URL配置:pythonfrom django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('blog/', include('blog.urls')), ]
创建模型
在blog/models.py
中定义文章模型:
python
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
运行迁移命令创建数据库表:
bash
python manage.py makemigrations
python manage.py migrate
创建视图
在blog/views.py
中定义视图函数:
python
from django.shortcuts import render, get_object_or_404
from .models import Post
def index(request):
posts = Post.objects.all()
return render(request, 'blog/index.html', {'posts': posts})
def detail(request, post_id):
post = get_object_or_404(Post, pk=post_id)
return render(request, 'blog/detail.html', {'post': post})
创建模板
在blog/templates/blog/
目录下创建模板文件:
-
base.html
(基础模板):html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}My Blog{% endblock %}</title> </head> <body> <header> <h1>My Blog</h1> </header> <main> {% block content %} {% endblock %} </main> <footer> <p>© 2024 My Blog</p> </footer> </body> </html>
-
index.html
(文章列表页面):html{% extends "blog/base.html" %} {% block title %}Blog Posts{% endblock %} {% block content %} <h2>Blog Posts</h2> <ul> {% for post in posts %} <li> <a href="{% url 'blog:detail' post.id %}">{{ post.title }}</a> <small>Published on {{ post.created_at|date:"Y-m-d" }}</small> </li> {% endfor %} </ul> {% endblock %}
-
detail.html
(文章详情页面):html{% extends "blog/base.html" %} {% block title %}{{ post.title }}{% endblock %} {% block content %} <h2>{{ post.title }}</h2> <p>{{ post.content }}</p> <p>Published on {{ post.created_at|date:"Y-m-d" }}</p> <a href="{% url 'blog:index' %}">Back to posts</a> {% endblock %}
配置应用的URL
在blog/urls.py
中定义应用的URL:
python
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.index, name='index'),
path('<int:post_id>/', views.detail, name='detail'),
]
运行项目
-
创建超级用户:
bashpython manage.py createsuperuser
-
运行开发服务器:
bashpython manage.py runserver
-
访问
http://127.0.0.1:8000/blog/
查看文章列表页面,访问http://127.0.0.1:8000/blog/1/
查看文章详情页面(需要先在后台创建文章).
这个示例项目展示了如何使用Django的模板系统创建一个简单的博客应用,包括基础模板、列表页面和详情页面的模板配置和使用.