目录css
""" Django模板语言 Django的模板语言旨在在功能和易用性之间取得平衡。它让那些习惯使用HTML的人感到舒服。 若是您对其余基于文本的模板语言(如Smarty 或Jinja2)有过接触,那么您应该对Django的模板感到宾至如归。 哲学 若是您有编程背景,或者习惯于将编程代码直接混合到HTML中的语言,那么您须要记住, Django模板系统不只仅是嵌入到HTML中的Python。这是一种设计,模板系统用于表达,而不是程序逻辑。 Django模板系统提供的标签功能相似于一些编程结构 如 if,布尔,for标签,循环标签等 - 但这些标签不是简单地做为相应的Python代码执行, 模板系统不会执行任意Python表达式。默认状况下,仅支持下面列出的标记,过滤器和语法(您能够根据须要将本身的扩展添加到模板语言中)。 哲学 为何使用基于文本的模板而不是基于XML的模板(如Zope的TAL)?咱们但愿Django的模板语言不只可用于XML / HTML模板。 在World Online,咱们将其用于电子邮件,JavaScript和CSV。您能够将模板语言用于任何基于文本的格式。 哦,还有一件事:让人类编辑XML是虐待狂! """
模板只是一个文本文件。它能够生成任何基于文本的格式(HTML,XML,CSV等)。 模板包含变量,这些变量在评估模板时将替换为值,而变量则包含控制模板逻辑的标记。 只要是在html里面有模板语法就不是html文件了,这样的文件就叫作模板。
模板语句的注释 {#{{ '10'|add_str:'5 '}}#} {#注释内容#}
变量:语法为 {{ }}:括号里加要渲染变量的变量值,变量名由字母数字和下划线组成。html
代码python
#views 文件函数 def template_test(request): name = '钢蛋' age = 18 hobby = ['唱', '跳', 'rap', '篮球'] lis = [] st = '' dic = { 'name': '铁蛋', 'age': 16, 'hobby': hobby, 'keys': 'xxxxx' } dic_2 = {} return render(request,'template_test.html', {'name':name_p,'age':age,'hobby':hobby,'lis':lis,'st':st,'dic':dic,'dic_2':dic_2}) # 模板文件html页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>郭楷丰</title> </head> <body> {{ 啦啦啦啦啦 }} <p> {{ name }} </p> <p> {{ age }} </p> <p> {{ hobby }} </p> <p> {{ lis }} </p> <p> {{ st }} </p> <p> {{ dic }} </p> <p> {{ dic_2 }} </p> </body> </html>
#views 文件函数 def template_test(request): lis = [1, 2, 3,4,5] dic = {"name": "黑蛋"} class Person(object): def __init__(self, name, age): self.name = name self.age = age def dream(self): return " 我 is {} age {}岁...".format(self.name,self.age) gangdan = Person(name="钢蛋", age=18) goudan = Person(name="狗蛋", age=17) tiedan = Person(name="铁蛋", age=16) person_list = [gangdan, goudan, tiedan] return render(request, "template_test.html", {"lis": lis, "dic": dic, "person_list": person_list}) # 模板文件html页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>郭楷丰</title> </head> <boby> <p>{{ lis.0 }}</p> <!--取l中的第一个参数--> <p>{{ dic.name }}</p><!--取字典中key的值--> <p>{{ person_list.0.name }}</p><!--取对象的name属性--> <p>{{ person_list.0.dream }}</p><!--.操做只能调用不带参数的方法--> </boby> </html>
#注:当模板系统遇到一个(.)时,会按照以下的顺序去查询: 1. 在字典中查询 2. 属性或者方法 3. 数字索引 # 索引不能为负数
{% for foo in lis %} <!--for循环--> {% if %} <!--if判断--> {% elif %} <!--elif判断--> {% endif %} <!--if闭合符--> {% else %} <!--else判断不成立执行--> {% endfor %} <!--for循环闭合符--> <!--应用 模板html代码--> <form action="" method="post"> <label for="inputEmail3" class="col-sm-2 control-label">书名: </label> <div class="col-sm-8"> <input type="text" name="book_name" class="form-control" value="{{ edit_obj.title }}"> <select name="pub_id" id="" class="btn btn-default btn-sm"> {% for foo in publishers %} {% if foo == edit_obj.pub %} <option selected value="{{ foo.pk }}"> {{ foo.name }}</option> {% else %} <option value="{{ foo.pk }}"> {{ foo.name }}</option> {% endif %} {% endfor %} </select> </div> <div class="text-center text-danger">{{ error }}</div> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">提交</button> </div> </form> <!--应用 python逻辑代码 #views 文件函数--> def edit_book(request): error = '' pk = request.GET.get('pk') edit_obj = models.Book.objects.filter(id=pk) if not edit_obj: return HttpResponse('要编辑的数据不存在') if request.method == 'POST': book_name = request.POST.get('book_name') if not book_name.strip(): error = "书名不能为空" pub_id = request.POST.get('pub_id') if edit_obj[0].title == book_name and edit_obj[0].pub_id == int(pub_id): error = "未做修改" if not error: obj = edit_obj[0] obj.title = book_name obj.pub_id = int(pub_id) obj.save() return redirect('/book_list/') publishers = models.Publisher.objects.all() return render(request,'edit_book.html',{'edit_obj':edit_obj[0],'publishers':publishers,'error':error})
js,python,模板语言的判断逻辑web
#python 10>5>1 =》 10>5 and 5>1 true #js 10>5>1 =》 10>5 =》 true =》 1>1 false #模板中 不支持连续连续判断,也不支持算数运算(过滤器)
Django的模板语言不支持连续判断,也不支持如下写法:django
{% if a > b > c %} ... {% endif %} #不支持算数运算 + - * /
def xx(request): d = {"a": 1, "b": 2, "c": 3, "items": "100"} return render(request, "xx.html", {"data": d})
{{ data.items }} 默认会取d的items key的值。
Variable | Description |
---|---|
forloop.counter |
当前循环的索引值(从1开始) |
forloop.counter0 |
当前循环的索引值(从0开始) |
forloop.revcounter |
当前循环的倒序索引值(到1结束) |
forloop.revcounter0 |
当前循环的倒序索引值(到0结束) |
forloop.first |
当前循环是否是第一次循环(布尔值) |
forloop.last |
当前循环是否是最后一次循环(布尔值) |
forloop.parentloop |
本层循环的外层循环 |
#for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,能够有所操做。 {% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
用来修改变量的显示结果, 语法: {{ value|filter_name:参数 }} ':' 左右没有空格没有空格没有空格编程
#写法一 {% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %} #写法二 {% with business.employees.count as total %} {{ total }} employee{{ total|pluralize }} {% endwith %}
{{ value|default:"nothing"}} 若是value值没传的话就显示nothing 注:TEMPLATES的OPTIONS能够增长一个选项:string_if_invalid:'找不到',能够替代default的的做用。 (在配置文件settings.py设置)
{{ value|filesizeformat }} 若是 value 是 123456789,输出将会是 117.7 MB
{{ value|add:"2" }} value是数字4,则输出结果为6 {{ value|add:"hello" }} value是数字666,则输出结果为666hello {{ first|add:second }} 若是first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6]
{{ value|lower }}
{{ value|upper}}
{{ value|title }}
"{{ value|ljust:"10" }}"
"{{ value|rjust:"10" }}"
"{{ value|center:"15" }}"
{{ value|length }} 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
{{value|slice:"2:-1"}}
{{ value|first }}
{{ value|last }}
{{ value|join:" // " }}
{{ value|cut:' ' }}
#参数:截断的字符数 {{ value|truncatechars:9}} truncatewords 按照单词进行截断, 只针对英文(...)不计数,中文按字计算
#后端 import datetime def mul(request): value = datetime.datetime.now() return render(request, 'mul.html',{'value':value}) #模板语句 {{ value|date:"Y-m-d H:i:s"}} #显示格式 年-月-日 时:分:秒 #后端 import datetime def mul(request): now = datetime.datetime.now() return render(request, 'mul.html',{'now':now}) #模板直接使用变量 {{ now }} #显示格式 June 19,2019,22:00 p.m. #时间格式和默认值一块儿使用 {{ obj.next_date|date:"Y-m-d"|default:"暂无" }}
#settings.py文件设置 USE_L10N = False #更换为False DATETIME_FORMAT = 'Y-m-d H:i:s' #添加 #也能够日期与时间分开设置 根据本身的需求设置 DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s'
XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆, 故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它容许恶意web用户将代码植入到提供给其它用户使用的页面中。 XSS是一种常常出如今web应用中的计算机安全漏洞,它容许恶意web用户将代码植入到提供给其它用户使用的页面中。 好比这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。 这种类型的漏洞因为被骇客用来编写危害性更大的网络钓鱼(Phishing)攻击而变得广为人知。对于跨站脚本攻击, 骇客界共识是:跨站脚本攻击是新型的“缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。
#Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。 可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的, 这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。 为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。
#页面代码: {% load my_tags %} {{ 'https://www.baidu.com/'|show:'百度' }} #自定过滤器代码 @register.filter def show(url,name): return "<a href = '{}'>{}</a>".format(url,name)
#自定过滤器代码 @register.filter(is_safe = True) def show(url,name): return "<a href = '{}'>{}</a>".format(url,name)
页面效果
bootstrap
模板语句中加 safe 解除转义后端
#模板语句 {% load my_tags %} {{ 'https://www.baidu.com/'|show:'百度'|safe }}
页面效果
浏览器
自定义过滤器是只能带有一个或两个参数的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
#注意 在settings中的INSTALLED_APPS配置当前app,否则django没法找到自定义的simple_tag (模块名只能是templatetags)
2 在python中建立py文件,文件名能够自定义 如:(my_tags.py)安全
3 在py文件中写:
from django import template register = template.Library() #固定写法,不可改变
@register.filter #过滤器 def add_str(value, arg): # 最多有两个 return '{}-{}'.format(value, arg)
{% load my_tags %} #先导入咱们自定义那个文件 my_tags {{ name|add_str:age }} #参数只能是两个,一个参数是变量name ,一个是参数是后面的那个参数age
#过滤器函数 @register.filter def multiply1(value,arg): return value * arg #模板语句 {% load my_tags %} <p>{{ 6|multiply1:'6' }}</p> <p>{{ 6|multiply1:6 }}</p> <p>{{ '10'|multiply1:5 }}</p>
#过滤器函数 @register.filter def division(value,arg): return value / arg #模板语句 {% load my_tags %} <p>{{ 6|division:6 }}</p> <p>{{ 6|division:1 }}</p>
#过滤器函数 @register.filter def add(value,arg): return value + arg #能够这样写,可是转换不了会报错 int(value) + int(arg) #模板语句 {% load my_tags %} <p>{{ 6|add:6 }}</p> <p>{{ 6|add:0 }}</p> <p>{{ '钢蛋g'|add:18 }}</p>
#过滤器函数 @register.filter def add(value,arg): return value - arg #模板语句 {% load my_tags %} <p>{{ 6|add:6 }}</p> <p>{{ 6|add:0 }}</p>
与自定义filter相似(也是在python包的templatetags文件下,建立此标签),只不过接收更灵活的参数。 #simple_tag 代码 @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" %} #例子 标签代码 @register.simple_tag def join_str(*args, **kwargs): return '{} - {} '.format('*'.join(args), '$'.join(kwargs.values())) # 模板 {% load my_tags %} {% join_str '1' '2' '钢蛋' k1='3' k2='4' %}
#分页显示代码 <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for i in num %} <li><a href="#">{{ i }}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> #页面1 {% load my_tags %} {% page 5 %} #页面2 {% load my_tags %} {% page 1 %}
自定义过滤器 filter 只能接受两个参数 调用的时候使用 {{ filter }} 自定义标签 simpletag 与自定义过滤器区别,能够接受更多参数,使用标签引用{{% %} 自定义标签 inclusion_tag 多用于返回html代码片断,使用标签引用{{% %}
在页面的form表单里面写上{% csrf_token %}
#做用 在配置文件找到静态文件别名,与文件地址进行拼接,这样别名改了,也不会影响,静态文件的导入 {% 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 %} <link rel="stylesheet" href="{% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %}"> <link rel="stylesheet" href="{% static '/css/dsb.css' %}"> {% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %} {% get_static_prefix %} # 获取别名
普通的HTML页面 母版页用于处理html页面相同部份内容,避免出现冗余代码,减小重复html页面的编写,提升代码复用性,方便代码修改.
#在子页面中在页面最上方使用下面的语法来继承母板。 {% extends '母版文件名.html' %}
经过在母板中使用{% block xxx %}来定义"块"。 在子页面中经过定义母板中的block名来对应替换母板中相应的内容。 #定义block {% block 块名 %} {% endblock %} #还能够{{% endblock 块名 %}}来关闭标签,更加清新 #使用block {% block 块名 %} #本身的内容 {% endblock %} #母版内容和本身内容都使用 {% block 块名 %} #本身的内容 {% block.super %} {% endblock %}
注意的点: 1. {% extends 'base.html' %} 写在第一行 前面不要有内容 有内容会显示 2. {% extends 'base.html' %} 'base.html' 加上引号 否则当作变量去查找 3. 把要显示的内容写在block块中 4. 定义多个block块,定义 css js 块
#做用 能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方按以下语法导入便可。 #示列 单独建一个html page <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for i in num %} <li><a href="#">{{ i }}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> #别的页面 引用 {% include 'page.html' %}