您的位置:首页 > 编程语言 > Go语言

django模板

2021-06-26 19:45 2251 查看

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 上下文变量管理器

对于使用方法,见:https://docs.djangoproject.com/zh-hans/3.2/ref/templates/builtins/

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 %} 标签中的内容总是被用作后备。
你可以根据需要使用任意层次的继承。一种常见的使用继承的方式是像以下的三层继承:

  1. 创建一个 base.html 模板,以保持你网站的主要外观和风格。
  2. 为你网站的每个“部分”创建一个 base_SECTIONNAME.html 模板。
    例如,base_news.html、base_sports.html。这些模板都是对 base.html 的扩展,并包括特定部分的样式/设计。
  3. 为每种类型的页面创建单独的模板
    如新闻文章或博客条目。这些模板扩展了相应的部分模板。

下面是一些关于继承工作的技巧:

  1. 如果你在模板中使用 {% extends %},它必须是该模板中的第一个模板标签。否则,模板继承将无法使用。
  2. 基础模板中的 {% block %} 标签越多越好。记住,子模板不需要定义所有的父块,所以你可以在一些块中填入合理的默认值,然后只定义以后需要的块。钩子多比钩子少好。
  3. 如果你发现自己的内容在多个模板中重复,可能意味着你应该把这些内容移到父模板中的 {% block %}。
  4. 如果你需要从父模板中获取块的内容,{{ block.super }} 变量就可以做到这一点。如果你想添加到父模板的内容中,而不是完全覆盖它,这很有用。使用 {{ block.super }} 插入的数据不会被自动转义,因为如果需要的话,它已经在父模板中被转义了。
  5. 通过使用与继承模板相同的模板名称,{% 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,所以其在常规位置定义的标签都可以在模板中自动加载。
自定义标签

  1. app中创建一个名为templatetags的Python 包
  2. 在templatetags下创建一个py文件,用于放标签函数
  3. 创建一个函数
  4. 使用
    django.template.Library
    对象的
    simple_tag
    方法装饰,可以指定name参数,表示标签名,空的时候为函数名
  5. 重启django
  6. 在template中使用load标签将自定义标签引入
  7. {% 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>

自定义过滤器

  1. app中创建一个名为templatetags的Python 包
  2. 在templatetags下创建一个py文件,用于放过滤器函数
  3. 创建一个函数
  4. 使用
    django.template.Library
    对象的
    filter
    方法装饰,可以指定name参数,表示过滤器名,空的时候为函数名
  5. 重启django
  6. 在template中使用load标签将自定义过滤器引入
  7. {{ 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>

我的github
我的博客
我的笔记

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: