Django模板
配置#
在settings.py中配置,BACKEND
表示要使用那种模板引擎;DIRS
表示template的目录(可以是多个);APP_DIRS
表示是否使用app中的template目录(即形如这样的app/templates/
);OPTIONS
是DjangoTemplates
的一些参数,默认即可。
比如:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, "templates"), ], 'APP_DIRS': True, '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', ], }, }, ]
要是想使用Jinja2:把BACKEND
改为django.template.backends.jinja2.Jinja2
即可。
当使用多个模板引擎时,django会按照列表的顺序找到html文件,然后渲染。需要注意的是:django查找到任何一个匹配的模板后便停止搜寻,所以这是个类似url搜索的短路操作!
使用#
一般来说我们可以使用django.shortcuts.render
指定template文件,然后进行渲染:
from django.shortcuts import render def index(request): return render(request, "app01/index.html")
render背后其实是这样的:
from django.template import loader from django.http import HttpResponse def render(request, template_name, context=None, content_type=None, status=None, using=None): content = loader.render_to_string(template_name, context, request, using=using) return HttpResponse(content, content_type, status)
render的参数
- request是一个HttpRequest对象
- template_name:一般来说一个HTML文件,其路径需要在settings中配置好
- context:需要传一个字典,里面的键值对可以在html页面中供模板引擎使用
- content_type:内容类型
模板语言#
django作为一个重型web框架,自然少不了模板语言。这主要是用于动态渲染HTML页面的。
变量#
使用两个大括号获取,对于对象的属性等数据可以在其基础上是用.
获取。对于Model对象,可以通过.
来取值,也可以使用.xxx_set
的方式进行反向查找,但查找操作不太适合在模板中完成。
比如:
# views.py from django.shortcuts import render def index(request): data = { "username": "lczmx", "age": 22, } msg_list = ["1234", "abcd", "6666"] print(request.session.get("")) return render(request, "app01/index.html", {"data": data, "msg_list": msg_list})
<!-- app01/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> <p>{{ data.username }}</p> <p>{{ data.age }}</p> <p>{{ msg_list.0 }}</p> </body> </html>
标签#
django模板引擎的标签就相当于python的代码块,以{% %}
的定义。
django已经为我们贴心地内置了一下标签 :
标签 | 作用 |
---|---|
autoescape | 自动转义开关 |
block | 块引用 |
comment | 注释 |
csrf_token | CSRF令牌 |
cycle | 循环对象的值 |
debug | 调试模式 |
extends | 继承模版 |
filter | 过滤功能 |
firstof | 输出第一个不为False的参数 |
for | 循环对象 |
for … empty | 带empty说明的循环 |
if | 条件判断 |
ifchanged | 如果有变化,则.. |
include | 导入子模版的内容 |
load | 加载标签和过滤器 |
lorem | 生成无用的废话 |
now | 当前时间 |
regroup | 根据对象重组集合 |
resetcycle | 重置循环 |
spaceless | 去除空白 |
templatetag | 转义模版标签符号 |
url | 获取url字符串 |
verbatim | 禁用模版引擎 |
widthratio | 宽度比例 |
with | 上下文变量管理器 |
对于使用方法,见django tag
as语法的使用
使用as语法可以将返回值赋值给一个变量,如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> {% url "app01:index" as index_url %} <a href="{{ index_url }}">index page</a> </body> </html>
模板继承:
extends与block结合,可以让你的一些模板继承其他模板,从而极大地减少代码的复用程度。
模板继承允许你建立一个基本的“骨架”模板,它包含了你网站的所有常用元素,并定义了子模板可以覆盖的 块。
我们先看一个例子,看看模板继承:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css"> <title>{% block title %}My amazing site{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block content %}{% endblock %} </div> </body> </html>
这个模板,我们称之为base.html
,它定义了一个 HTML 骨架文档,你可以用它来制作一个两栏式页面。“子”模板的工作是用内容填充空块。
在这个例子中,block 标签定义了三个块,子模板可以填入其中。block 标签所做的就是告诉模板引擎,子模板可以覆盖模板的这些部分。
一个子模板可能是这样的:
{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
extends 标签是这里的关键。它告诉模板引擎,这个模板“扩展”了另一个模板。当模板系统执行这个模板时,首先要找到父模板——在本例中是“base.html”。
这时,模板引擎会注意到 base.html 中的三个 block 标签,然后用子模板的内容替换这些块。根据 blog_entries 的值,输出可能是这样的:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css"> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="content"> <h2>Entry one</h2> <p>This is my first entry.</p> <h2>Entry two</h2> <p>This is my second entry.</p> </div> </body> </html>
请注意,由于子模板没有定义 sidebar
块,所以使用父模板的值来代替。父模板中 {% block %} 标签中的内容总是被用作后备。
你可以根据需要使用任意层次的继承。一种常见的使用继承的方式是像以下的三层继承:
- 创建一个 base.html 模板,以保持你网站的主要外观和风格。
- 为你网站的每个“部分”创建一个 base_SECTIONNAME.html 模板。
例如,base_news.html、base_sports.html。这些模板都是对 base.html 的扩展,并包括特定部分的样式/设计。 - 为每种类型的页面创建单独的模板
如新闻文章或博客条目。这些模板扩展了相应的部分模板。
下面是一些关于继承工作的技巧:
- 如果你在模板中使用 {% extends %},它必须是该模板中的第一个模板标签。否则,模板继承将无法使用。
- 基础模板中的 {% block %} 标签越多越好。记住,子模板不需要定义所有的父块,所以你可以在一些块中填入合理的默认值,然后只定义以后需要的块。钩子多比钩子少好。
- 如果你发现自己的内容在多个模板中重复,可能意味着你应该把这些内容移到父模板中的 {% block %}。
- 如果你需要从父模板中获取块的内容,{{ block.super }} 变量就可以做到这一点。如果你想添加到父模板的内容中,而不是完全覆盖它,这很有用。使用 {{ block.super }} 插入的数据不会被自动转义,因为如果需要的话,它已经在父模板中被转义了。
- 通过使用与继承模板相同的模板名称,{% extends %} 可以在覆盖模板的同时继承它。结合 {{ block.super }},这可以成为一种强大的小规模定制方式。 比如官方给出的这个例子:扩展复写模板。
在 {% block %}
之外使用模板标签 as
语法创建的变量不能在块中使用。例如,这个模板不会呈现任何东西:
{% translate "Title" as title %} {% block content %}{{ title }}{% endblock %}
为了增加可读性,你可以给你的 {% endblock %}
标签 起一个 名字。例如:
{% block content %} ... {% endblock content % }
在较大的模板中,这种技术可以帮助你看到哪些 {% block %}
标签正在被关闭。
最后,请注意,你不能在同一个模板中定义多个同名的 block 标签。
过滤器#
过滤器就相当于python语法中的函数,其使用语法是:{{ 变量 | 过滤器:参数 }}
,其中,对于没有参数的过滤器来说,:参数
这部分省略。
内置过滤器
过滤器 | 说明 |
---|---|
add | 加法 |
addslashes | 添加斜杠 |
capfirst | 首字母大写 |
center | 文本居中 |
cut | 切除字符 |
date | 日期格式化 |
default | 设置默认值 |
default_if_none | 为None设置默认值 |
dictsort | 字典排序 |
dictsortreversed | 字典反向排序 |
divisibleby | 整除判断 |
escape | 转义 |
escapejs | 转义js代码 |
filesizeformat | 文件尺寸人性化显示 |
first | 第一个元素 |
floatformat | 浮点数格式化 |
force_escape | 强制立刻转义 |
get_digit | 获取数字 |
iriencode | 转换IRI |
join | 字符列表链接 |
json_script | 生成script标签,带json数据 |
last | 最后一个 |
length | 长度 |
length_is | 长度等于 |
linebreaks | 行转换 |
linebreaksbr | 行转换 |
linenumbers | 行号 |
ljust | 左对齐 |
lower | 小写 |
make_list | 分割成字符列表 |
phone2numeric | 电话号码 |
pluralize | 复数形式 |
pprint | 调试 |
random | 随机获取 |
rjust | 右对齐 |
safe | 安全确认 |
safeseq | 列表安全确认 |
slice | 切片 |
slugify | 转换成ASCII |
stringformat | 字符串格式化 |
striptags | 去除HTML中的标签 |
time | 时间格式化 |
timesince | 从何时开始 |
timeuntil | 到何时多久 |
title | 所有单词首字母大写 |
truncatechars | 截断字符 |
truncatechars_html | 截断字符 |
truncatewords | 截断单词 |
truncatewords_html | 截断单词 |
unordered_list | 无序列表 |
upper | 大写 |
urlencode | 转义url |
urlize | url转成可点击的链接 |
urlizetrunc | urlize的截断方式 |
wordcount | 单词计数 |
wordwrap | 单词包裹 |
yesno | 将True,False和None,映射成字符串‘yes’,‘no’,‘maybe’ |
一般的使用例子,以add为例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> <p>你明年的年龄是{{ data.age | add:1 }}</p> </body> </html>
其他的内置过滤的参考。
关于safe字符串,见:几种safe字符串的方法
自定义标签及过滤器#
一般来说,默认的标签和过滤器已经够我们应付简单场景的了,面对复杂的需求的话,我们可以使用自定义标签和过滤器的办法。
自定义标签及过滤器的位置就是 Django 应用内。如果它们关联至某个已存在的应用,在那里将它们打包就很有用;否则,它们能被添加至新应用。当一个 Django 应用被添加至 INSTALLED_APPS,所以其在常规位置定义的标签都可以在模板中自动加载。
自定义标签
- app中创建一个名为templatetags的Python 包
- 在templatetags下创建一个py文件,用于放标签函数
- 创建一个函数
- 使用
django.template.Library
对象的simple_tag
方法装饰,可以指定name参数,表示标签名,空的时候为函数名 - 重启django
- 在template中使用load标签将自定义标签引入
- 以
{% xx %}
的形式使用
例子:
# 第1和第2步省略 # app的目录机构(部分): # app01 # ├── admin.py # ├── apps.py # ├── templatetags # │ ├── __init__.py # │ ├── mytags.py # │ └── __pycache__ # │ ├── __init__.cpython-38.pyc # │ └── mytags.cpython-38.pyc # ├── tests.py # ├── urls.py # └── views.py
# app01/templatetags/mytags.py from django import template # 第4步 register = template.Library() # 指定name参数为t1,在template中就只能用t1了 @register.simple_tag(name="t1") def my_tag(x, y, *args): print(x, y) print(args) return "t1"
{# 使用load自定义标签,mytags是py文件,t1是name指定的参数, 若不指定,则为函数名#} {% load t1 from mytags %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> {# 使用t1标签 #} {% t1 12 234 134 %} </body> </html>
自定义过滤器
- app中创建一个名为templatetags的Python 包
- 在templatetags下创建一个py文件,用于放过滤器函数
- 创建一个函数
- 使用
django.template.Library
对象的filter
方法装饰,可以指定name参数,表示过滤器名,空的时候为函数名 - 重启django
- 在template中使用load标签将自定义过滤器引入
- 以
{{ xx | yy:z}}
的形式使用
filter和tag很像,就装饰器、函数参数、模板使用方法有所区别,例子:
# app01/templatetags/myfilter.py from django import template register = template.Library() @register.filter(name="f1") def my_filter(x, y, z): print(x, y, z) return "f1"
{# 使用load自定义过滤器,myfilter是py文件 #} {% load f1 from myfilter %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> {# 使用f1过滤器 #} {{ "hello"|f1:123 }} </body> </html>
load标签的使用
load是用于加载一个自定义模板标签集。
上面在例子使用了load标签,下面记录一下其语法。
在使用时可以把load类比成python的import
比如现在在templatetags下有两个文件,每个文件中有一个标签或过滤器函数:
# app/templatetags/myfilter.py from django import template register = template.Library() @register.filter(name="f1") def my_filter(x, y): print(x, y) return "f1" # ########################################################## # # app/templatetags/myfilter.py from django import template register = template.Library() @register.simple_tag(name="t1") def my_tag(x, y, *args): print(x, y) print(args) return "t1"
那么就有两种方法加载:
第一种
{# load的是py文件#} {% load mytags %} {% load myfilter %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> {# 直接使用 #} {% t1 12 234 134 %} {{ "hello"|f1:123 }} </body> </html>
方法二:
此方法可以同时加载多个,以空格隔开,如:{% load f1 f2 from myfliter %}
{#{% load t1 from mytags %}#} {#{% load f1 from myfilter %}#} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>app01 index</title> </head> <body> {# 使用 #} {% t1 12 234 134 %} {{ "hello"|f1:123 }} </body> </html>
作者:忞翛
出处:https://www.cnblogs.com/lczmx/p/14938874.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
欢迎各位大佬评论交流。可以的话,不妨点一下推荐。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp