官方文档css
Django模板中只须要记两种特殊符号:html
{{ }}和 {% %}python
{{ }}表示变量,在模板渲染的时候替换成值,{% %}(表示标签)表示逻辑相关的操做。数据库
{{ 变量名 }}django
变量名由字母数字和下划线组成。bootstrap
点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。浏览器
几个例子:安全
view中代码:服务器
def template_test(request):
li = [11, 22, 33]
dic = {"name": "mcw"}
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def dream(self):
return "{} is dream...".format(self.name)
ma = Person(name="ma", age=18)
hong = Person(name="hong", age=9000)
ming = Person(name="ming", age=18)
person_list = [ma,hong,ming]
return render(request, "template_test.html", {"li": li, "dic": dic, "person_list": person_list}) #传字符串,数字,列表,字典等
模板中支持的写法:app
<p>
取li中的第一个参数 :<br>
{{ li.0 }} <br> {# 列表.索引,而不是列表[索引] #}
取字典中key的值: <br>
{{ dic.name }} <br> {# 字典.键 而不是字典['键'] #}
取对象的name属性(对象变量),能够连着取 :<br>
{{ person_list.0.name }} <br> {# person_list.0是ma对象,对象.name取实例变量 #}
操做只能调用不带参数的方法 :<br>
{{ person_list.0.dream }}<br> {# person_list.0是ma 对象,对象.方法(而不是对象.方法())调用不带参数的方法#}
</p>
也能够这样多行传递并渲染:render拿到模板文件和变量并将模板文件替换而后发送给浏览器,是python作的渲染
字符串 数字 列表 字典
列表索引不能用负数取值,报错:
取值:
字典中的值也能够点下去,get方法不能用。类的返回值很差看,能够用str方法
取字典中的数据:支持keys values items
注:当模板系统遇到一个(.)时,会按照以下的顺序去查询:
如今字典中找,而不是先使用keys方法
翻译为过滤器,用来修改变量的显示结果。
语法: {{ value|filter_name:参数 }}
':'左右没有空格没有空格没有空格
有空格报错:
default
{{ value|default:"nothing"}}
若是value值没传的话就显示nothing
没传值或者布尔值为False的彷佛都是显示nothing,至关于没传值
注:TEMPLATES的OPTIONS能够增长一个选项:string_if_invalid:'找不到',能够替代default的的做用。
filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
若是 value 是 123456789,输出将会是 117.7 MB。
add
给变量加参数
{{ value|add:"2" }}
value是数字4,则输出结果为6。
{{ first|add:second }}
若是first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。
数字和字符串类型的数字使用add,怎么拼获得的都是数字运算的结果;数字和非数字字符串使用add方法彷佛没有结果;非数字字符串和非数字字符串,数字字符串和非数字字符串都是字符串拼接
lower
小写
{{ value|lower }}
upper
大写
{{ value|upper}}
title
标题
{{ value|title }}
ljust
左对齐
"{{ value|ljust:"10" }}"
rjust
右对齐
"{{ value|rjust:"10" }}"
center
居中
"{{ value|center:"15" }}"
length
{{ value|length }}
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
slice
切片
{{value|slice:"2:-1"}}
first
取第一个元素
{{ value|first }}
last
取最后一个元素
{{ value|last }}
join
使用字符串拼接列表。同python的str.join(list)。
{{ value|join:" // " }}
truncatechars
若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 truncatewords
参数:截断的字符数
{{ value|truncatechars:9}}
date
日期格式化
{{ value|date:"Y-m-d H:i:s"}}
可格式化输出的字符:点击查看。 没有% M->i S->s
或者修改配置
USE_L10N = False
DATETIME_FORMAT="Y-m-d H:i:s"
#还有DATA_FORMAT TIME_FORMAT
safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。 转义是防止XSS攻击的
好比:
value = "<a href='#'>点我</a>"
{{ value|safe}}
若是博客评论里面能够将js插入到程序里面,而后这是一个循环一万次的alert,那么老是进不了网页,而在页面老是弹出alert框,直到循环结束。某些网站就是这样,陷入死循环退不出去浏览器,只能重启浏览器了
为了安全起见,会变成字符串展现在页面,若是想让它变成程序使用,添加 safe
没有safe的是被转义过了的,因此在页面不是a标签显示出来,而是纯文本显示。
若是传进的有safe,那么safe前面传进的是不断循环alert,那么这个网页就会执行不少这次alert而进不了网页。它的做用就是告诉django这里不须要转义
自定义过滤器只是带有一个或两个参数的Python函数:
例如,在过滤器{{var | foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”。
自定义filter代码文件摆放位置:
app01/ __init__.py models.py templatetags/ # 在app01下面新建一个package package __init__.py app01_filters.py # 建一个存放自定义filter的py文件 views.py
编写自定义filter
from django import template register = template.Library() @register.filter def fill(value, arg): return value.replace(" ", arg) @register.filter(name="addSB") def add_sb(value): return "{} SB".format(value)
使用自定义filter
{# 先导入咱们自定义filter那个文件 #} {% load app01_filters %} {# 使用咱们自定义的filter #} {{ somevariable|fill:"__" }} {{ d.name|addSB }}
已导入,仍是报错:'my_tags' is not a registered tag library. Must be one of:
遇到这个,第一步重启项目。报错变了
缘由,L应该大写,Library()
实现替换:
命名错误,在python这个包的init文件里随便写点东西,报错。
这里名称必须正确且与这个一致,写错会报错:
手动建立的一个目录而不是在pycharm中建立的包也行,可是没有init文件,能够补充一个,不过尽可能仍是建立包好些;
from django import template registers=template.Library() @registers.filter def fill(value, arg): #最多两个参数,一个过滤器的变量,一个你想要的参数 return value.replace(" ", arg) #将渲染值中的空格替换为你想要的arg @registers.filter(name="addSB") def add_sb(value): #给要渲染的值作一个操做,并给过滤器函数起个名字 return "{} SB".format(value) #第二个传参要不要都行。将传进来作渲染的数据通过自定义过滤器作一次操做以后
过滤器另取个名以后,函数名就无效了:
改为新起的名字就行了:
for
根据多个值,对每一个值作不一样的操做
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul>
for循环可用的一些参数:
Variable | Description |
---|---|
forloop.counter |
当前循环的索引值(从1开始) |
forloop.counter0 |
当前循环的索引值(从0开始) |
forloop.revcounter |
当前循环的倒序索引值(到1结束) |
forloop.revcounter0 |
当前循环的倒序索引值(到0结束) |
forloop.first |
当前循环是否是第一次循环(布尔值) |
forloop.last |
当前循环是否是最后一次循环(布尔值) |
forloop.parentloop |
本层循环的外层循环 |
当前循环的索引值(从0开始)
循环计数倒叙,但不影响列表取值顺序:
倒叙循环计数,索引最值小为0 当前循环的倒序索引值(到0结束)
当前循环是否是第一次循环(布尔值) 当前循环是否是最后一次循环(布尔值)
若是只有一个元素,那么既是第一个也是最后一个
若是只是打印forloop那么显示的是一个字典,字典里有刚才的那些变量,而后.出来值,还有一个就是parentloop循环是空值,由于这里没有使用外层循环
如今传进去是一个列表里面套着几个列表:取出来每一个元素都是列表;
如今展现列表里面的内容,须要再来一次内层循环:
每一行都是一个外层循环,一行中的每列都是在内层循环。一行中的每列的parentloop都是相同的,是同一个外层循环,prentloop的rarentloop没有值,由于父的循环往上就没有循环了
第二行就是循环计数第二个的外层循环,而后当前外层循环下进行内层循环展现每列的内容
last和first是只的是每一个for循环的
将表格偶数列变成红色字体:若是循环计数是偶数,那么在内存循环中给这列加上颜色
若是想要实现偶数行而且是偶数列的单元格是红色字:那么加一个and共判断两个条件。外层定义行,内层定义了列。内层中获取它的循环序数,也能获取外层循环的序号;
偶数行和偶数列才变红:内层循环判断,知足循环序数是偶数且父循环序数也是偶数才添加样式
for ... empty
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空空如也</li> {% endfor %} </ul>
<table border="1"> <thead> <tr> <th>序号</th> <th>ID</th> <th>书名</th> <th>出版社</th> <th>操做</th> </tr> </thead> <tbody> {% for book in books %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.pk }}</td> <td>{{ book.title}}</td> <td>{{ book.pub}}</td> <td><a href="/del_book/?pk={{ book.pk }}">删除</a> <a href="/edit_book/?pk={{ book.pk }}">编辑</a> </td> </tr> {% empty %} <td colspan="5" style="text-align: center;">没有相关的数据</td> {% endfor %} </tbody>
将数据都删除
若是数据库中没有查询到数据,这样显示不友好:
当显示为空的时候给用户一个提示,而不是误觉得有问题:
再让它居中一下。合并一下。
if,elif和else
{% if user_list %} 用户人数:{{ user_list|length }} {% elif black_list %} 黑名单数:{{ black_list|length }} {% else %} 没有用户 {% endif %}
固然也能够只有if和else
{% if user_list|length > 5 %} 七座豪华SUV {% else %} 黄包车 {% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
pycharm中连续比较 真:比较原理是 10>5是真,5>1是真,两次比较结果再and作个比较,结果是真
控制台中连续比较 假:比较原理是10>5是true, true>1比较是false。所以两种比较方式不一样,结果不一样
以下在js控制台中就显示true了,10>5是true ,true==1 结果就是true
模板语言和js是相同的,连续大于要空格,虽然报红可是不影响结果显示
不能使用1+2==判断,而是要用过滤器计算而后判断是否==
with
定义一个中间变量。(定义变量,起别名)
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %}
{% with business.employees.count as total%} {{ total }} employee{{ total|pluralize }} {% endwith %}
hobby_list.0.2
内容太长或者是列表中连续索引取值而不能清楚取值是什么,这时候用 with起个别名
这个标签用于跨站请求伪造保护。
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,一般缩写为CSRF或者XSRF,是一种对网站的恶意利用。
在页面的form表单里面写上{% csrf_token %}
跨站请求的理解:
用户 a 服务器b 服务器c
从a到b请求,b返回a中可能有form表单。表单中action提交的地址常常不写,不写默认是提交到当前的地址。若是form表单中的地址是另外一个网站的地址(服务器c),这样你的post请求就不是服务器b,而是去请求服务器c另外一个网站的了,这就叫跨站请求。对于服务器c来讲它没有作任何校验,任何人都能对它进行post请求
对于我们来讲应该是从a请求c,获取到页面,而后填写帐号密码以及转帐的用户和金额,填写完后点击提交post请求进行转帐。若是你是不当心点击广告等进入的是钓鱼网站服务器b等等,这样你就说从b中获取的转帐提交网页,钓鱼网站的form表单中没有填写action,那么post请求的是钓鱼网站b,可是服务器B中的网站写了c的ation。那么你作的是c的post转帐请求,看着是如出一辙的是提交到c的,可是若是b的请求网页中内部作了一些修改将你的转帐帐号修改为了他人的帐号,那么你就转帐到了非法帐户中了,这客户就产生了损失。c不能随便就能提交post请求的,须要校验,不承认从别人的服务器form表单提交过来的请求。正常的应该是从a请求c获取的form标签再提交到c。那么应该怎样区别出是c本身的form提交仍是b跨站来的form表单提交给b呢?那么服务器c就要作个标记,用户获取到它的网页并用这个网页提交post请求那么会把标记提交回来。若是是从b获取的form表单页面那么a是没有c给的标记,这样a写好form表单以后再提交到c那么就校验不经过了。
假如a是从b拿到的请求,b返回a的页面。这时a又从c出得到了请求c须要携带的标记,再去往c发送请求,这样c也就承认它了。这就是跨站请求伪造,a从c经过csrf从c获取到标记而后渲染到a从c获取的form表单页面,这样c处校验跨站请求就能经过,不然不能经过校验就不能用b的form表单post提交到action是c地址的c服务器
在配置中把这个注释去掉:
这下post请求就会被拒绝了。由于当前服务器还不能肯定是谁的网页发送的post请求
全部要想本身发出去的页面中提交的post请求能经过校验,那么要在发送出去的网页中添加标签 {% csrf_token %},标签写在form表单外的时候以下。
这样网页并无显示什么不一样。可是网页中有了一个{% csrf_token %}渲染出来的类型是隐藏的input标签,名字是csrf中间件token,值是一串字符
这样的话我要请求,就能够拿到下面三个键值对,其中包括csrf的token。
标签写在form表单外面get能渲染token进模板,可是post没有获取到token
将它放在form表单中才能在post请求获取到csrf中间件的token值,才能在服务器端根据这个值作校验,校验成功才能正常访问,不然403拒绝
{# ... #} #这个注释不作渲染
<!-- {{可使用渲染的内容}} --> #这个注释作渲染,可是不在浏览器上展现出来,在开发工具的元素中能够看到它是存在的,它做为代码提示用的
1. Django的模板语言不支持连续判断,即不支持如下写法:
{% if a > b > c %} ... {% endif %}
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的值。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> {% block page-css %} {% endblock %} </head> <body> <h1>这是母板的标题</h1> {% block page-main %} {% endblock %} <h1>母板底部内容</h1> {% block page-js %} {% endblock %} </body> </html>
注意:咱们一般会在母板中定义页面专用的CSS块和JS块,方便子页面替换。
下面的书籍列表页面:
和下面的页面能够作成一致的,也须要用下面的出版社样式,若是只是复制粘贴使用共有展现的东西的话,可能复制出问题,并且多个页面中含有的重复的代码特别多。而且一个页面作了公共部分的修改了,那么每一个页面都要作修改,这是代码重复的问题,那么代码重复须要一直复制粘贴不少次,python中减小代码重复是写函数和类。父类里面写个属性,方法,用的时候子类继承这个父类,每一个子类想用不一样的方法和属性那么从新定义,覆盖掉父类中相同的方法和属性。这是继承,继承在模板页面也是相似的
那么1处,2处的公共的部分须要分出来做为模板 ,而3处做为变化的要替换的内容;
下面就建立基础模板,并删掉上面那个网页中多余出来的变化的部分:
先把咱们须要的模板访问展现出来,1处就是变化的部分,其它部分是公共的功能,已经把公共的部分提出了了。
在你删掉的那部分代码处添加block块:它就至关于公共的类和方法。
建立母版的思想就是将页面公共的地方提取出来,将须要子页面都须要添加内容的地方添加block块,而后子页面中用代码将这个block块替换掉
publisher_list.html这个页面中将公共的部分删掉,并将刚才删掉的部分留下,导入base.html母版,删掉的部分做为变化的替换掉上面名称为content的block块。
<html lang="en"> <head> <meta charset="UTF-8"> <title>魔降风云变</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css"> <link href="/static/css/dashboard.css" rel="stylesheet"> </head> {#<body>#} <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">图书管理系统</a> </div> <div id="navbar" class="navbar-collapse collapse"> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Dashboard</a></li> <li><a href="#">Settings</a></li> <li><a href="#">Profile</a></li> <li><a href="#">Help</a></li> </ul> <form class="navbar-form navbar-right"> <input type="text" class="form-control" placeholder="Search..."> </form> </div> </div> </nav> <div class="container-fluid"> <div class="row"> <div class="col-sm-3 col-md-2 sidebar"> <ul class="nav nav-sidebar"> <li class="active"><a href="/publisher_list/">出版社列表 <span class="sr-only">(current)</span></a></li> <li><a href="#">Reports</a></li> </ul> </div> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">出版社列表</h3> </div> <div class="panel-body"> <a class="btn btn-success btn-sm" href="/add_publisher">新增</a> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>序号</th> <th>ID</th> <th>名称</th> <th>操做</th> </tr> </thead> <tbody> {% for publisher in all_publishers %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.pk }}</td> <td>{{ publisher.name }}</td> <td> <a class="btn btn-danger btn-sm" href="/del_publisher/?id={{ publisher.pk }}">删除</a> <a class="btn btn-success btn-sm" href="/edit_publisher/?id={{ publisher.pk }}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </div> </div> </body> </html>
/publisher_list/ 导入模板成功显示公共功能部分
在publisher.html页面中再添加模板中能够替换的block块content部分。在子html中将刚才删除的内容添加进去:
而后子页面就使用继承的方法正常显示了
下面把下面的book_list.html页面也修改为这个模板的。
这里只显示模板没有显示book的数据,由于以前这里函数改为了模板页面了,改回来
book页面也用这个模板渲染出来了:
将表格样式用publisher_list.html中的样式修改一下:
左边书籍列表添加要在base母版修改添加:
虽然实现了,可是都是被选中状态,由于这两个标签都有active类
若是没有这个类是未被选中状态:
那么就用block块的方法代替它 ,点击哪一个页面的时候先将模板全部的变成空,而后将点击的要显示这个html添加active类
重名了:
换个名字,如今都是未被选中:
给这里默认填充一个内容让它被选中:
而后在子中替换掉:实现点击谁只有谁被选中并展现出来
我也能够直接用publisher.html作母版,将变化的内容写在block里面,而后子继承父,子中将对应block内容重写替换掉父的。拿一个子类当成父类,其它继承这个父类。咱们要作的就是把页面中特殊的替换掉。用base或者某个页面作母版看状况而定
总结:
就是一个普通HTML提取多个页面的公共部分 定义block块
继承:
{% extends ‘base.html’ %}
重写block块 —— 写子页面独特的内容
注意的点:
{% extends 'base.html' %} 写在第一行 前面不要有内容 有内容会显示
{% extends 'base.html' %} 'base.html' 加上引号 否则当作变量去查找
把要显示的内容写在block块中
写在第一行母版以前:一、{% extends 'base.html' %} 写在第一行 前面不要有内容 有内容会显示
写在块的外面;{% extends 'base.html' %} 'base.html' 加上引号 否则当作变量去查找
把继承中的模板去掉引号:它会把它当作变量(或者变量没有正确获取)并报错:Invalid template name in 'extends' tag: ''. Got this from the 'base.html' variable.
那么将母版以变量的形式从函数中传进来并在子中继承:之后想要灵活点,能够换模板那么就将母版以变量的形式传递进来。
注意:咱们有的时候想要子页面有不一样的样式或js,而不是只能使用父的,所以咱们一般会在母板中定义页面专用的CSS块和JS块,方便子页面替换。
{% block page-css %} {% endblock %}
<h1>母板底部内容</h1> {% block page-js %} {% endblock %}
在子页面中在页面最上方使用下面的语法来继承母板。
{% extends 'layouts.html' %}
经过在母板中使用{% block xxx %}
来定义"块"。
在子页面中经过定义母板中的block名来对应替换母板中相应的内容。
{% block page-main %} <p>世情薄</p> <p>人情恶</p> <p>雨送黄昏花易落</p> {% endblock %}
能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方按以下语法导入便可。
组件就是实现一角的功能的一小段代码块
{% include 'navbar.html' %}
那么这里也可使用模板和继承,那么我把base的左边框和内容部分替换掉,这样的话要替换的比较多。 更方便的是把导航栏作成一个组件,将它导入到新增页面,就像Python里的模块,想用导入就好了。
如今把母版里的导航栏剪切下来:
剪切下来继承使用它的就没有这个导航栏了,剪切下来放到一个html文件
可是页面仍是要使用导航栏的功能,导入这个组件便可,这就是一部分代码块(放到里面就能使用展现想要效果的代码块;将一个功能剪切出去放到html文件就实现了一个组件,这个代码块就是组件)
而后直接导入组件 include 加组件文件名字
{% include 'nav.html' %}
以下就将以前想要添加的部分功能添加到这个页面了:由于多个页面都是导入的这一个组件,那么只要修改这个组件,好比把图书管理系统名字改掉,只须要在组件 中修改就能够把全部用这个组件的页面显示都修改为新的名字了。
一小段代码块
若是未来部署的过程中,静态文件别名想要作个变动,不想用这个名字了,那么换了名字以后就这样了:
1处修改,2和3的引用使用的固定的没有修改这样4处样式就没有使用上了
而且这里报错找不到,由于别名修改了而引用路径没有修改。引用必须和别名一致才能找到样式。那么若是手动修改引用的别名的话,修改那么多个确定不方便
那么把这个别名的引用变成变量的那种形式来使用,让它本身去找这个别名而后替换成当前配置的别名;
首先导入,而后使用,若是没有传参会报错至少一个传参,开头有没有/均可以:
它会给你作上拼接:
staticfiles也能够的
导入static使用这个tag那么获取到的是静态目录的那个别名:
使用它来的话这里不能加/,就是获取别名而后渲染上了,不会给你添加/
{% 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>
{% 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!" />
和自定义filter相似,只不过接收更灵活的参数。
定义注册simple tag 。simpletag前面和filter类似,就是使用不一样的装饰器传递的参数数量不一样
@register.simple_tag(name="plus") def plus(a, b, c): return "{} + {} + {}".format(a, b, c)
使用自定义simple tag
{% load app01_demo %} {# simple tag #} {% plus "1" "2" "abc" %}
多用于返回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}
templates/result.html
<ul> {% for choice in data %} <li>{{ choice }}</li> {% endfor %} </ul>
templates/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>inclusion_tag test</title> </head> <body> {% load my_inclusion %} {% show_results 10 %} </body> </html>
使用下面的分页:
可是这个是固定死的页数,修改一下:
1)1处写函数,将参数传到函数中。返回一个字典。这里字典的一个值是1-10的列表吧,
2)1处将page函数返回值渲染page.html代码段中的内容造成一个代码段
3)3处导入这个模块,使用这个标签函数,并指定传参。这样引用并生成灵活可变更的page.html代码段,并在这个页面中渲染出来。
4)就至关于我生成一个可传参修改变更的组件,而后将组件导入到须要的页面。根据 须要产生细微差异
参考连接:https://www.cnblogs.com/maple-shaw/articles/9333821.html