Django模板渲染
Posted fdsimin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django模板渲染相关的知识,希望对你有一定的参考价值。
{{ 变量 }}
{% 逻辑 %}
变量使用
看示例
Views.py文件
def home(request): class A: def __init__(self): self.username = ‘bob‘ #如果方法需要在模板中使用,那么不能有其他参数 def xx(self): return ‘bobxx‘ info = { ‘name‘: ‘jack‘, ‘hobby‘: [‘running‘, ‘walking‘, ‘reading‘], ‘num‘: 100, ‘d1‘:{‘aa‘:‘bb‘}, ‘l1‘:[11,22,{‘cc‘:‘dd‘}], ‘a‘: A(), } return render(request, ‘home.html‘, info)
重点:万能的据点号。通过点可以进行数据的索引取值,属性取值,取方法等等
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>{{ name }}</h2> <ul> {% for i in hobby %} <li>{{ i }}</li> {% endfor %} </ul> <hr> {{ num }} <p> {{ l1.2.ss }} </p> <p> {{ d1.xx }} </p> <p> {{ a.username }} </p> <p> {{ a.xx }} <!-- 方法不能加括号,意味着不能穿参数,也就是说你后面定义的方法,不能有参数 --> </p> </body> </html>
urls.py内容
url(r‘^home/‘, views.home),
在Django的模板语言中,通过使用 过滤器 来改变变量的显示。
过滤器的语法:{{ value|filter_name:参数 }}
使用过滤器的注意事项
1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
2. {{ sss|过滤器1:30|过滤器2.... }}
3. 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
4. ‘|‘左右没有空格
内置过滤器
常用的内置过滤器示例
(1) default
如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
{{ value|default:"nothing"}}
如果value没有传值或者值为空或者为False的话就显示nothing
(2) length
{{ value|length }}
返回value的长度,如 value=[‘a‘, ‘b‘, ‘c‘, ‘d‘]的话,就显示4.
(3) filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 ‘13 KB‘
, ‘4.1 MB‘
, ‘102 bytes‘
, 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。
(4) slice
切片,如果 value="hello world",还有其他可切片的数据类型
{{value|slice:"2:-1"}}
(5) date
格式化,如果 value=datetime.datetime.now(),如果不想显示为UTC时间,将django的settings.py配置文件中的TIME_ZONE这一项修改一下,修改为TIME_ZONE = ‘Asia/Shanghai‘
比如,后台返回的数据为{‘value‘:datetime.datetime.now()}
?
对上面的数据进行格式化:{{ value|date:"Y-m-d H:i:s"}}
关于时间日期的可用的参数(除了Y,m,d等等)还有很多,有兴趣的可以去查查看看。
(6) safe
xxs攻击,全称跨站脚本攻击 Django的模板中在进行模板渲染的时候会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全,django担心这是用户添加的数据,比如如果有人给你评论的时候写了一段js代码,这个评论一提交,js代码就执行啦,这样你是不是可以搞一些坏事儿了,写个弹窗的死循环,那浏览器还能用吗,是不是会一直弹窗啊,这叫做xss攻击,所以浏览器不让你这么搞,给你转义了。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
{‘a_tag‘:‘<a href="">百度</a>‘,} 渲染 <p> {{ a_tag|safe }} #生成标签效果 </p>
(7) truncatechars
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数
{{ value|truncatechars:9}} #注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,有人会说,怎么展开啊,配合前端的点击事件就行啦
(8) truncatewords
在一定数量的字后截断字符串,是截多少个单词。
例如:‘are you ok’,
{{ value|truncatewords:2}} #上面例子得到的结果是 ‘are you...‘
(9) cut
移除value中所有的与给出的变量相同的字符串
{{ value|cut:‘ ‘ }}
如果value为‘i love you‘,那么将输出‘iloveyou‘.
(10) join
使用字符串连接列表,{{ list|join:‘, ‘ }},就像Python的str.join(list)
<p>{{ hobby|join:‘+‘ }}</p>
注意:模版渲染在浏览器渲染之前,模板渲染就是字符串替换,替换完成之后,将替换完的整体文件字符串返回给浏览器,浏览器再进行浏览器渲染,展示页面效果
标签
语法{% 标签 %}
(1) for循环标签
示例:
#循环列表 <ul> {% for xx in hobby %} <li>{{ xx }}</li> {% empty %} #当hobby为空或者后台没有给这个数据,那么会显示empty下面的内容 <h2>抱歉,没有查询到相关数据</h2> {% endfor %} </ul> #循环字典 <ul> {% for k,v in d1.items %} <!-- 直接循环字典数据,那么是循环字典的key,循环d1.values,那么表示循环字典的值, 循环d1.items,那么k,v表示键和值--> <li>{{ k }}--{{ v }}</li> {% endfor %} </ul> #循环计数 <ul> {% for i in l1 %} {# {{ forloop }}#} {% for h in hobby %} <li>{{ forloop.parentloop.counter }}--{{ forloop.revcounter0 }}---{{ h }}--{{ forloop.last }}</li> {% endfor %} {% endfor %} </ul> forloop的解释 注:循环序号可以通过{{forloop}}显示,必须在循环内部用 forloop.counter 当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能 forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(从1开始) forloop.revcounter0 当前循环的倒序索引值(从0开始) forloop.first 当前循环是不是第一次循环(布尔值) forloop.last 当前循环是不是最后一次循环(布尔值) forloop.parentloop 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等 #反向循环 可以利用{% for obj in list reversed %}反向完成循环。 示例: <ul> {% for xx in hobby reversed %} <li>{{ xx }}</li> {% endfor %} </ul>
(2) if 标签
{% if %}
会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %} <p>无效</p> <!--不满足条件,不会生成这个标签--> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <!--也是在if标签结构里面的--> <p>凑活吧</p> {% endif %}
当然也可以只有if和else
{% if user_list|length > 5 %} <!--结合过滤器来使用--> 七座豪华SUV {% else %} 黄包车 {% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
(3) with标签
使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
例如:
注意等号左右不要加空格。
{% with total=business.employees.count %} {{ total }} <!--只能在with语句体内用--> {% endwith %}
或
{% with business.employees.count as total %}
{{ total }}
{% endwith %}
使用标签的注意事项
1. Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %}
...
{% endif %}
Django的模板语言中属性的优先级大于方法(了解)
def xx(request):
d = {"a": 1, "b": 2, "c": 3, "items": "100"}
return render(request, "xx.html", {"data": d})
如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:
{{ data.items }}
默认会取d的items key的值。
自定义标签和过滤器
自定义过滤器
注意:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
1、在app中创建templatetags文件夹(文件夹名只能是templatetags)
2、在templatetags文件夹中创建任意 .py 文件,如:mytag.py
3、在mytag.py文件中写上如下内容
from django import template register = template.Library() #制作注册器,名字必须叫register #过滤最多两个参数 @register.filter #注册过滤器,需要两个参数的 def add(v1, v2): #v1表示管道符前面的,v2表示冒号后面的参数 print(v1,v2) #100 50 return v1 + v2 @register.filter #注册过滤器,需要一个参数的 def xxx(v1): #v1表示管道符前面的 print(v1) return ‘xxx‘
4、使用,在html文件中写上如下内容
{% load mytag %} <!-- 首先通过load来加载一下mytag文件,不一定放在文件的开头,但是一定要放在使用过滤器的前面先进行引用 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>base页面</h1> <!--{% load mytag %} 放这里也是可以的--> <div> {{ num|add:50}} <!-- 使用过滤器,和django内置过滤器用法一样,这里生成的是add函数的返回值 --> </div> <div> {{ num|xxx }} </div> <!--{% load mytag %} 放这里不行--> </body> </html>
自定义标签
过程:
1、在app中创建templatetags文件夹(文件夹名只能是templatetags)
2、在templatetags文件夹中创建任意 .py 文件,如:mytag.py
3、在mytag.py文件中写上如下内容
from django import template register = template.Library() #制作注册器,名字必须叫register @register.simple_tag def atag(v1,v2): #没有参数个数限制 print(v1,v2) return v1 + v2
4、使用,在html文件中写上如下内容
{#{% load mytag %}#} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>base页面</h1> {% load mytag %} <div> {% atag ‘a‘ ‘b‘ %} <!-- 注意,是{%%} 来包裹使用,先是标签名称然后空格写参数,参数之间也是空格分隔的 --> </div> </body> </html>
将一些页面公共的部分,可以抽离出来单独做成一个html页面,使用这些公用部分的其他html文件,只需要继承一下它就可以了,具体使用流程如下:
1 创建公用模板,比如内容如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ padding: 0; margin: 0; } {% block css %} .nav{ height: 60px; background-color: green; } {% endblock %} .nav a{ color:white; text-decoration: none; } .left-menu{ width: 30%; background-color: rgba(0,0,0,0.5); float:left; } .menu .menu-title{ text-align: center; } .main{ float: right; width: 65%; height: 300px; border: 1px solid red; } </style> </head> <body> <div class="nav"> <a href="/xx1/">首页</a> <a href="/person/">个人中心</a> <a href="/detail/">详情页</a> </div> <div class="left-menu"> <div class="menu"> <div class="menu-title">菜单1</div> <div class="menu-body"> <div class="item">包子</div> <div class="item">馒头</div> <div class="item">凉皮</div> <div class="item">面条</div> </div> <div class="menu-title">菜单2</div> <div class="menu-body"> <div class="item">排骨藕汤</div> <div class="item">粉蒸肉</div> <div class="item">腊鱼块</div> <div class="item">灌肠</div> </div> </div> </div> <div class="main"> {% block content %} 公共页面 {% endblock %} </div> </body> {% block js %} {% endblock %} </html>
2 将来如果说继承公用模板的html文件中需要修改公用模板中的一些内容,那么需要在公用模板中预留一些钩子,钩子的写法如下
{% block content %} #block 后面的块名称随便起
公共页面
{% endblock %}
#也可以这样写 {% endblock content %} #endblock指定名称
3 继承公用模板需要在html文件中写如下内容:
{% extends ‘xx.html‘ %} <!-- 需要先继承一下公用模板,写法就是extends ‘公用模板文件名称‘,注意,必须写在第一行 --> {% block css %} .nav{ height: 60px; background-color: pink; } {% endblock %} {% block content %} <h1>首页</h1> {% endblock %}
4 在使用公用模板的其他html文件中,如果需要更改公用模板里面的内容,只需要在html文件中写上相同的钩子,钩子里面写上自定义的内容,写法如下
{% block css %} .nav{ height: 60px; background-color: pink; } {% endblock %} {% block content %} <h1>首页</h1> {% endblock %}
注意事项:
-
如果你在模版中使用
{% extends %}
标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作,模板渲染的时候django都不知道你在干啥。 -
在base模版中设置越多的
{% block %}
标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。 -
如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个
{% block %}
中。 -
{{ block super }}的使用,在子模板中也展示出父模板原来钩子中的内容
{% block content %} <h1>首页</h1> {{ block.super }} {% endblock %}
{% block content %}
...
{% endblock content %}
在大型模版中,这个方法帮你清楚的看到哪一个 {% block %}
标签被关闭了。
不能在一个模版中定义多个相同名字的 block
标签。
#两个block都叫content,这种写法是不对的 {% block content %} <h1>首页</h1> {{ block.super }} {% endblock %} {% block content %} <h1>首页</h1> {{ block.super }} {% endblock %}
以上是关于Django模板渲染的主要内容,如果未能解决你的问题,请参考以下文章