1、DTL模板标签
在for循环中,DTL提供了一些变量可供使用。
forloop.counter:当前循环的下标。以1作为起始值。forloop.counter0: 当前循环的下标。以0作为起始值。forloop.revcounter: 当前循环的反向下标值。比如列表有5个元素,那么第一次遍历这个属性是等于5,第二次是4,以此类推。并且是以1作为最后一个元素的下标。forloop.revcounter0: 类似于forloop.revcounter。不同的是最后一个元素的下标是从0开始。forloop.first: 是否是第一次遍历。forloop.last: 是否是最后一次遍历。forloop.parentloop: 如果有多个循环嵌套,那么这个属性代表的是上一级的for循环。
for…in…empty标签:这个标签使用跟for…in…是一样的,只不过是在遍历的对象如果没有元素的情况下,会执行empty中的内容。
{% for person in persons %}<li>{{ person }}</li>{% empty %}暂时还没有任何人{% endfor %}
注意:在for循环中,break,continue语句是用不了的。
1. url标签
url标签:在模版中,我们经常要写一些url,比如某个a标签中需要定义href属性。当然如果通过硬编码的方式直接将这个url写死在里面也是可以的。但是这样对于以后项目维护可能不是一件好事。因此建议使用这种反转的方式来实现,类似于django中的reverse一样。
<a href="{% url 'book:list' %}">图书列表页面</a>
如果url反转的时候需要传递参数,那么可以在后面传递。但是参数分位置参数和关键字参数。位置参数和关键字参数不能同时使用。
# path部分path('detail/<book_id>/',views.book_detail,name='detail')# url反转,使用位置参数<a href="{% url 'book:detail' 1 %}">图书详情页面</a># url反转,使用关键字参数<a href="{% url 'book:detail' book_id=1 %}">图书详情页面</a>
如果想要在使用url标签反转的时候要传递查询字符串的参数,那么必须要手动在在后面添加。
<!-- ?page=1是字符串拼接 --><a href="{% url 'book:detail' book_id=1 %}?page=1">图书详情页面</a>
如果需要传递多个参数,那么通过空格的方式进行分隔。
<!-- 传递多个参数使用空格分离 --><a href="{% url 'book:detail' book_id=1 page=2 %}">图书详情页面</a>
with标签
<!-- with语句 -->{% with name=person.0 %}{{ name }}{% endwith %}<!-- with语句 -->{% with person.0 as name %}{{ name }}{% endwith %}
autoescape 自动转义标签
视图文件:book/views.py,传递参数到前端页面进行渲染:
def book_detail(request):context = {"username": "12345","book": ["python", "java", "php"],"books": ("python", "java", "php"),"info": {"name": "xxxxx","url": "<a href=''>百度</a>", # 链接渲染到前端会因为源码中的render_to_string方法变成字符串},# 传递类"person": Person("ch")}# 注意第一个参数request要有 # render在源码中封装了render_to_string和HttpResponsereturn render(request, "book_detail.html", context=context)
前端页面渲染book_detail.html:
<!--info中的链接会自动转换成字符串,自动转义-->{{info.url}}<!-- 处理后的链接可以正常显示,关闭自动转义, off关闭,on打开 -->{% autoescape off %}}{{info.url}}{% endautoescape %}}
更多标签: /en/2.0/ref/templates/builtins/
创建新的Django项目:
2、模版常用过滤器
在模版中,有时候需要对一些数据进行处理以后才能使用。一般在Python中我们是通过函数的形式来完成的。而在模版中,则是通过过滤器来实现的。过滤器使用的是|来使用。
add
将传进来的参数添加到原来的值上面。这个过滤器会尝试将值和参数转换成整形然后进行相加。如果转换成整形过程中失败了,那么会将值和参数进行拼接。如果是字符串,那么会拼接成字符串,如果是列表,那么会拼接成一个列表。
{{value|add:"2" }}
如果value是等于4,那么结果将是6。如果value是等于一个普通的字符串,比如abc,那么结果将是abc2。
实例如下:
from django.shortcuts import renderfrom django.template import defaultfiltersdef index(request):context = {"num": 2,"str": 'abc', }return render(request, 'index.html', context=context)
index.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><h1>测试</h1><p> 首页</p><!-- 前端页面int类型加1操作 --><p>{{ num|add:"1" }}</p><!-- 前端页面str类型加1操作 --><p>{{ str|add:"1" }}</p><!-- 前端页面str类型加字符串操作 --><p>{{ str|add:"xxxxx" }}</p></body></html>
列表相加相当于列表拼接。
cut
移除值中所有指定的字符串。类似于python中的replace(args,"")。
{{ value|cut:" " }}
前端页面渲染如下:
date
将一个日期按照指定的格式,格式化成字符串。
# 数据context = {"birthday": datetime.now()}# 模版{{ birthday|date:"Y/m/d" }}
<!-- date使用 --><p>{{ birthday }}</p><p>{{ birthday|date:"Y/m/d" }}</p><p>{{ birthday|date:"Y/m/d H:i:s" }}</p>
default
如果值被评估为False。比如[],"",None,{}等这些在if判断中为False的值,都会使用default过滤器提供的默认值。
{{ value|default:"nothing" }}
如果value是等于一个空的字符串。比如"",那么以上代码将会输出nothing。
<!-- default使用 --><p>{{ info|default:"暂时没有设置签名" }}</p>
上面代码中info如果有值,会显示views.py中传输过来的值,如果没有,会显示default:“暂时没有设置签名”。
first
返回列表/元组/字符串中的第一个元素。
{{value|first }}
last
返回列表/元组/字符串中的最后一个元素。
{{value|last }}
def index(request):context = {"num": 2,"str": 'abc',"birthday": datetime.now(),"info": "个性签名","l1": [1, 2, 3, 4, 5, 6, 7, 8],"z1": ("1", "2", "3", "4"),}return render(request, 'index.html', context=context)index.html文件中渲染:<p>{{l1|first }}</p><p>{{l1|last }}</p><p>{{z1|first }}</p><p>{{z1|last }}</p>
floatformat
使用四舍五入的方式格式化一个浮点类型。如果这个过滤器没有传递任何参数。那么只会在小数点后保留一个小数,如果小数后面全是0,那么只会保留整数。当然也可以传递一个参数,标识具体要保留几个小数。
<!-- ul标签是无序列表标签 ,显示结果为34.334.434.353 --><ul><li>{{ 34.32|floatformat }}</li><li>{{ 34.35|floatformat }}</li><li>{{ 34.353333|floatformat:3}}</li></ul>
join
类似与Python中的join,将列表/元组/字符串用指定的字符进行拼接.
{{ value|join:"/" }}
如果value是等于[‘a’,‘b’,‘c’],那么以上代码将输出a/b/c。
length
获取一个列表/元组/字符串/字典的长度。
{{ value|length }}
如果value是等于[‘a’,‘b’,‘c’],那么以上代码将输出3。如果value为None,那么以上将返回0。
lower
将值中所有的字符全部转换成小写。
{{ value|lower }}
upper
类似于lower,只不过是将指定的字符串全部转换成大写。
random
在被给的列表/字符串/元组中随机的选择一个值。
{{ value|random }}
safe
标记一个字符串是安全的。也即会关掉这个字符串的自动转义。
<!-- 标记字符串是安全的,相当于关闭自动转义功能 -->{{value|safe}}
如果value是一个不包含任何特殊字符的字符串,比如这种,那么以上代码就会把字符串正常的输入。如果value是一串html代码,那么以上代码将会把这个html代码渲染到浏览器中。
slice
类似于Python中的切片操作。
{{ some_list|slice:"2:" }} 从第2个元素到最后的元素
striptags
删除字符串中所有的html标签。
{{ value|striptags }}
truncatechars
如果给定的字符串长度超过了过滤器指定的长度。那么就会进行切割,并且会拼接三个点来作为省略号。
{{ value|truncatechars:5 }}
更多可以查看Django源码
from django.template import defaultfilters,defaulttags
3、模版结构优化
引入模版
有时候一些代码是在许多模版中都用到的。如果我们每次都重复的去拷贝代码那肯定不符合项目的规范。一般我们可以把这些重复性的代码抽取出来,就类似于Python中的函数一样,以后想要使用这些代码的时候,就通过include包含进来。这个标签就是include。
# header.html<p>我是header</p># footer.html<p>我是footer</p># main.html{% include 'header.html' %}<p>我是main内容</p>{% include 'footer.html' %}
include标签寻找路径的方式。也是跟render渲染模板的函数是一样的。
默认include标签包含模版,会自动的使用主模版中的上下文,也即可以自动的使用主模版中的变量。如果想传入一些其他的参数,那么可以使用with语句。
# header.html<p>用户名:{{ username }}</p># main.html{% include "header.html" with username='xxx' %}<!-- with定义名称进行显示 -->
模板继承
在前端页面开发中。有些代码是需要重复使用的。这种情况可以使用include标签来实现。也可以使用另外一个比较强大的方式来实现,那就是模版继承。模版继承类似于Python中的类,在父类中可以先定义好一些变量和方法,然后在子类中实现。模版继承也可以在父模版中先定义好一些子模版需要用到的代码,然后子模版直接继承就可以了。并且因为子模版肯定有自己的不同代码,因此可以在父模版中定义一个block接口,然后子模版再去实现。
{% load static %}<!DOCTYPE html><html lang="en"><head><link rel="stylesheet" href="{% static 'style.css' %}" /><title>{% block title %}我的站点{% endblock %}</title></head><body><div id="sidebar">{% block sidebar %}<ul><li><a href="/">首页</a></li><li><a href="/blog/">博客</a></li></ul>{% endblock %}</div><div id="content">{% block content %}{% endblock %}</div></body></html>
这个是父模版,我们取名叫做base.html,定义好一个简单的html骨架,然后定义好两个block接口,让子模版来根据具体需求来实现。子模板然后通过extends标签来实现.
<!-- 继承父模板的信息 -->{% extends "base.html" %}{% block title %}博客列表{% endblock %}{% block content %}{% for entry in blog_entries %}<h2>{{ entry.title }}</h2><p>{{ entry.body }}</p>{% endfor %}{% endblock %}
模板继承注意点
extends标签必须放在模版的第一行。子模板中的代码必须放在block中,否则将不会被渲染。如果在某个block中需要使用父模版的内容,那么可以使用{{block.super}}来继承。比如上例,{%block title%},如果想要使用父模版的title,那么可以在子模版的title block中使用{{ block.super }}来实现。在定义block的时候,除了在block开始的地方定义这个block的名字,还可以在block结束的时候定义名字。比如{% block title %}{% endblock title %}。这在大型模版中显得尤其有用,能让你快速的看到block包含在哪里。子模板中的代码,如果没有放在{%block %}中,不会被渲染显示出来。4、加载静态文件
在一个网页中,不仅仅只有一个html骨架,还需要css样式文件,js执行文件以及一些图片等。因此在DTL中加载静态文件是一个必须要解决的问题。在DTL中,使用static标签来加载静态文件。要使用static标签,首先需要{% load static %}。
步骤如下:
1.首先确保django.contrib.staticfiles已经添加到settings.INSTALLED_APPS中。(默认已经添加)2.确保在settings.py中设置了STATIC_URL。(默认创建了)3.在已经安装了的app下创建一个文件夹叫做static,然后再在这个static文件夹下创建一个当前app的名字的文件夹,再把静态文件放到这个文件夹下。
默认添加了django.contrib.staticfiles
默认创建了STATIC_URL
创建static文件夹:
注意:为什么在app下创建一个static文件夹,还需要在这个static下创建一个同app名字的文件夹呢?
原因是如果直接把静态文件放在static文件夹下,那么在模版加载静态文件的时候就是使用logo.jpg,如果在多个app之间有同名的静态文件,这时候可能就会产生混淆。而在static文件夹下加了一个同名app文件夹,在模版中加载的时候就是使用app/logo.jpg,这样就可以避免产生混淆。
第四步如下:
4.如果有一些静态文件是不和任何app挂钩的。那么可以在settings.py中添加STATICFILES_DIRS,以后DTL就会在这个列表的路径中查找静态文件。
settings.py
# 指定静态文件目录STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
5.在模版中使用load标签加载static标签。比如要加载在项目的static文件夹下的style.css的文件。
{% load static %}<link rel="stylesheet" href="{% static 'style.css' %}">
6.如果不想每次在模版中加载静态文件都使用load加载static标签,那么可以在settings.py
中的TEMPLATES/OPTIONS
添加'builtins':['django.templatetags.static']
,这样以后在模版中就可以直接使用static标签,而不用手动的load了。
settings.py:这样设置会在加载静态资源文件的路径前加上/static/
路径
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')], # 模板路径设置'APP_DIRS': True,'OPTIONS': {# 不想每次在模版中加载静态文件都使用load加载static标签,以后在模版中就可以直接使用static标签,而不用手动的load了'builtins':['django.templatetags.static'],'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},]
这样在模版中就可以直接使用static标签,而不用手动的load了
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><!-- 加载静态资源文件中的css文件 --><link rel="stylesheet" href="{% static 'index.css' %}"></head>