1. 模板系统(字符串替换)
1. 语法
1. 变量相关: {{ name }},{{name|length}},{{name|default:"默认值"}}
2. 逻辑相关:
1. if判断
{% if a > b %}
{% endif %}
{% if a > b %}
{% else %}
{% endif %}
{% if a > b %}
{% elif %}
{% else %}
{% endif %}
2. for循环
1. for循环的基本用法:
{% for i in name_list %}
{{ i }}
{% endfor %}
{% for i in name_list %}
{{ i }}
{% empty %}
空空如也
{% endfor %}
2. for循环可用的属性:
forloop.counter
forloop.counter0
forloop.revcounter
forloop.revcounter0
forloop.first
forloop.last
forloop.parentloop --> 两层for循环,内层循环引用外层循环
2. filter
1. 常用的内置filter
1. length
2. filesizeformat --> 格式化文件大小的
3. date:'Y-m-d H:i:s' --> 格式化时间的
4. slice
5. safe --> XSS攻击(跨站脚本攻击)
6. truncatechars:20 --> 截取字符,超过的用...表示
7. default
2. 自定义的filter
示例:
1. addsb
2. addstr
具体的实现方式:
1. 定义阶段
1. 在app下面新建一个python的包:templatetags
2. 在上面的Python包中新建一个Python文件,名字随意
3. 在上述python文件中:
from django import template
# 生成一个注册用的实例
register = template.Library()
# 定义并注册一个自定义的filter函数
@register.filter(name='addsb')
def add_sb(arg):
return "{} sb".format(arg)
2. 调用阶段:
1. 在Django的模板文件中,导入刚才新建的python文件
{% load py文件名 %}
2. 按照filter的语法调用
{{ name|addsb }}
1. 模板语言(字符串替换) 1. 母版和继承 1. 什么时候用母版? html页面有重复的代码,把它们提取出来放到一个单独的html文件。 (比如:导航条和左侧菜单) 2. 子页面如何使用母版? {% extends 'base.html' %} --> 必须要放在子页面的第一行 母版里面定义block(块),子页面使用block(块)去替换母版中同名的块 2. 组件 1. 什么时候用组件? 重复的代码,包装成一个独立的小html文件。 2. 如何使用? {% include 'nav.html' %} 3. Django模板语言中关于静态文件路径的灵活写法 1. 利用Django模板语言内置的static方法帮我拼接静态文件的路径 {% load static %} <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet"> 2. 利用内置的get_static_prefix获取静态文件路径的别名,我们自行拼接路径 {% load static %} <link href="{% get_static_prefix %}bootstrap/css/bootstrap.min.css" rel=stylesheet> 3. as语法(一个路径多次用到,可以使用as保存到一个变量,后面就直接使用变量代替具体路径) 4. 自定义的simple_tag 比filter高级一点点 它可以接受的参数个数大于2 5. 自定义的inclusion_tag 用来返回一段html代码(示例:返回ul标签) 1. 定义阶段 在app下面新建templatetags 文件夹(注意是Python包) 新建一个py文件 from django import template # 生成注册示例,名字必须是register register = template.Library() @register.inclusion_tag("ul.html") def show_ul(num): num = 1 if num < 1 else int(num) data = ["第{:0>3}号技师".format(i) for i in range(1, num+1)] return {"data": data} 2. 调用阶段 {% load xx %} {% show_ul 10 %}
一、语言变量相关语法
只需要记两种特殊符号:
{{ }}和 {% %}
变量相关的用{{}},逻辑相关的用{%%}。
2、字典测试:
3、模板语言类与列表测试:
# 测试用类 class Person: def __init__(self, name, age): self.name = name self.age = age def run(self): return '{} 今天好开心,跑了三米'.format(self) def __str__(self): return '<Person-object {}>'.format(self.name) # 模板语言测试相关 def template_test(request): p1 = Person('小白', 9000) p2 = Person('小黑', 10000) p_list = [p1,p2] return render( request, "t_text.html", { "person1":p1, "person2":p2, "p_list":p_list })
二、模板语言之filter
在Django的模板语言中,通过使用 过滤器 来改变变量的显示。
过滤器的语法: {{ value|filter_name:参数 }}
使用管道符"|"来应用过滤器。
例如:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。
注意事项:
- 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
- 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
- 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
- '|'左右没有空格没有空格没有空格
Django的模板语言中提供了大约六十个内置过滤器。
1、default
如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
{{ value|default:"nothing"}}
如果value没有传值或者值为空的话就显示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|slice:"2:-1"}}
5、date
格式化
{{ value|date:"Y-m-d H:i:s"}}
from datetime import datetime now = datetime.now()
<p>时间格式化:{{ now|date:"Y-m-d H:i:s" }}</p>
6、safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
比如:
value = "<a href='#'>点我</a>"
{{ value|safe}}
例:
a_html = "<a href='http://www.sogo.com'>我是后端传过来的a标签</a>"
7、truncatechars
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数
{{ value|truncatechars:9}}
8、truncatewords
在一定数量的字后截断字符串。
{{ value|truncatewords:9}}
例:
p_str = """ 在苍茫的大海上,狂风卷积着乌云,在乌云和大海之间,海燕像黑色的闪电,在高傲地飞翔。 """
9、cut
移除value中所有的与给出的变量相同的字符串
{{ value|cut:' ' }}
如果value为'i love you',那么将输出'iloveyou'.
10、join
使用字符串连接列表,例如Python的str.join(list)
11、timesince
将日期格式设为自该日期起的时间(例如,“4天,6小时”)。
采用一个可选参数,它是一个包含用作比较点的日期的变量(不带参数,比较点为现在)。 例如,如果blog_date是表示2006年6月1日午夜的日期实例,并且comment_date是2006年6月1日08:00的日期实例,则以下将返回“8小时”:
{{ blog_date|timesince:comment_date }}
分钟是所使用的最小单位,对于相对于比较点的未来的任何日期,将返回“0分钟”。
12、timeuntil
似于timesince,除了它测量从现在开始直到给定日期或日期时间的时间。 例如,如果今天是2006年6月1日,而conference_date是保留2006年6月29日的日期实例,则{{ conference_date | timeuntil }}将返回“4周”。
使用可选参数,它是一个包含用作比较点的日期(而不是现在)的变量。 如果from_date包含2006年6月22日,则以下内容将返回“1周”:
{{ conference_date|timeuntil:from_date }}
13、自定义filter
自定义过滤器只是带有一个或两个参数的Python函数:
- 变量(输入)的值 - -不一定是一个字符串
- 参数的值 - 这可以有一个默认值,或完全省略
例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”。
步骤:
1、自定义filter代码文件摆放位置:
2. 在上面的Python包中新建一个Python文件,名字随意
2、在myfilter.py文件中编写自定义filter
from django import template # 生成一个注册用的实例 register = template.Library() # 定义并注册一个自定义的filter函数 # 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫nihao @register.filter(name="nihao") def add_nihao(arg): return "{} nihao.".format(arg) # 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫addstr @register.filter(name="addstr") def add_str(arg, arg2): """ 第一个参数永远是管道符前面那个变量 :param arg: 道符前面那个变量 :param arg2: 冒号后面的变量 :return: """ return "{} {}.".format(arg, arg2)
3、使用自定义filter
'name': '王镇',
{# 先导入我们自定义filter那个文件 #} {% load myfilter %} {# 使用我们自定义的filter #} {{ name|nihao }} {# 打印结果:王镇 nihao #} {{ name|addstr:"跑得快~" }} {# 打印结果:王镇 跑得快~ #} {{ name|addstr:"跳的高~" }} {# 打印结果:王镇 跳的高~ #}
三、Tags
1、注释
{# ... #}
2、for循环
(1)普通for循环:
<ul> {% for name in name_list %} <li>{{ name }}</li> {% endfor %} </ul>
for循环可用的一些参数:
示例:
name_list = ['张三', '李四', '王五']
<ul> {% for name in name_list %} {% if forloop.last %} <li class="dsb">{{ forloop.revcounter }}-{{ name }}</li> {% else %} <li class="{% if forloop.first %}'sb'{% endif %}">{{ forloop.revcounter }}-{{ name }}</li> {% endif %} {% endfor %} </ul>
(2)双层for循环:
name_list2 = [['张三0', '李四0', '王五0'], ['张三1', '李四1', '王五1']]
{% for name in name_list2 %}
{% for name1 in name %}
{{ forloop.parentloop.counter }}
{{ forloop.counter }}
{{ name1 }}
{% endfor %}
{% endfor %}
(2)for ... empty
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空空如也</li> {% endfor %} </ul>
如果user_list没有值就执行empty下面的语句
3、if判断
if,elif和
else
{% if p3 %} <p>p3:{{ p3 }}</p> {% elif p2 %} <p>p2:{{ p2 }}</p> {% else %} <p>什么人都没有!</p> {% endif %}
上面只有p2,所以执行p2下面的语句
当然也可以只有if和else
{% if name_list|length >= 3 %} <p>需要打两辆车</p> {% else %} <p>一辆足矣!</p>
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
4、with
定义一个中间变量,多用于给一个复杂的变量起别名。
注意等号左右不要加空格。
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
或
{% with business.employees.count as total %} {{ total }} employee{{ total|pluralize }} {% endwith %}
5、csrf_token
这个标签用于跨站请求伪造保护。
在页面的form表单里面写上{% csrf_token %}
6、注意事项
1. Django的模板语言不支持连续判断(python支持):
2. 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的值100。
例如:
四、母板和继承
1. 为什么要有模板和继承:
把多个页面公用的部分提取出来,放在一个 母版 里面。
其他的页面只需要 继承 母版就可以了。
2. 具体使用的步骤:
1. 把公用的HTML部分提取出来,放到base.html文件中
2. 在base.html中,通过定义block,把每个页面不同的部分区分出来
3. 在具体的页面中,先继承母版
4. 然后block名去指定替换母版中相应的位置
3. 使用母版和继承的注意事项:
1. {% extends 'base.html' %} --> 母版文件:base.html要加引号
2. {% extends 'base.html' %}必须放在子页面的第一行!!!
3. 可以在base.html中定义很多block,通常我们会额外定义page-css和page-js两个块
4. view.py相应的函数中返回的是对应的子页面文件 不是 base.html
1、继承母板
在子页面中在页面最上方使用下面的语法来继承母板。
{% extends 'layouts.html' %}
2、块(block)
通过在母板中使用{% block xxx %}
来定义"块"。
在子页面中通过定义母板中的block名来对应替换母板中相应的内容。
{% block page-main %} <p>世情薄</p> <p>人情恶</p> <p>雨送黄昏花易落</p> {% endblock %}
3、组件
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。
{% include 'navbar.html' %}
<!DOCTYPE html> <!-- saved from url=(0042)https://v3.bootcss.com/examples/dashboard/ --> <html lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="https://v3.bootcss.com/favicon.ico"> <title>图书管理系统</title> <!-- Bootstrap core CSS --> <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom styles for this template --> <link href="/static/dashboard.css" rel="stylesheet"> <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css"> {% block page-css %} {% endblock %} </head> <body> {% include 'navbar.html' %} <div class="container-fluid"> <div class="row"> <div class="col-sm-3 col-md-2 sidebar"> <ul class="nav nav-sidebar"> <li class="{% block publisher_class %}{% endblock %}"><a href="/publisher_list/">出版社列表页</a></li> <li class="{% block book_class %}{% endblock %}"><a href="/book_list/">书籍列表</a></li> <li class="{% block author_class %}{% endblock %}"><a href="/author_list/">作者列表</a></li> </ul> </div> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> {# 这里是每个页面不同的部分 #} {% block page-main %} {% endblock %} </div> </div> </div> </div> <div class="modal fade" tabindex="-1" role="dialog" id="myModal"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button> <h4 class="modal-title">用户信息</h4> </div> <div class="modal-body"> <form class="form-horizontal"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary">保存</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> <!-- Bootstrap core JavaScript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> {% block page-js %} {% endblock %} </body> </html>
五、静态文件相关
1、{% static %}
{% load static %} <img src="{% static "images/hi.jpg" %}" alt="Hi!" />
引用JS文件时使用:
{% load static %} <script src="{% static "mytest.js" %}"></script>
某个文件多处被用到可以存为一个变量
{% load static %} {% static "images/hi.jpg" as myphoto %} <img src="{{ myphoto }}"></img>
2、{% get_static_prefix %}(了解)
{% load static %} <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />
或者
{% load static %} {% get_static_prefix as STATIC_PREFIX %} <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
六、simple_tag
和自定义filter类似,只不过接收更灵活的参数。
定义注册simple_tag
@register.simple_tag(name="plus") def plus(a, b, c): return "{} + {} + {}".format(a, b, c)
使用自定义simple_tag
{% load mysimpletag %} {# simple_tag #} {% plus "1" "2" "abc" %}
七、inclusion_tag
多用于返回html代码片段
示例:
templatetags/my_inclusion.py
from django import template register = template.Library() @register.inclusion_tag('result.html') def show_results(n): n = 1 if n < 1 else int(n) data = ["第{}项".format(i) for i in range(1, n+1)] return {"data": data}
<ul> {% for choice in data %} <li>{{ choice }}</li> {% endfor %} </ul>
from django import template register = template.Library() @register.simple_tag(name="yimi") def my_sum(arg1, arg2, arg3): return "{} {} {}".format(arg1, arg2, arg3) @register.inclusion_tag('results.html') def show_results(n): n = 1 if n < 1 else int(n) data = ["第{}项".format(i) for i in range(1, n+1)] return {"results": data}