3.Django模板(Template)
常用语法·
{{ }} 和 {% %}
变量相关的用{{ }},逻辑相关的用{%%}。
模板渲染的官方文档
view中的代码
def template_test(request): l = [11, 22, 33] #列表 d = {"name": "alex"} #字典 class Person(object): def __init__(self, name, age): self.name = name self.age = age def dream(self): return "{} is dream...".format(self.name) Alex = Person(name="Alex", age=34) #自定义类对象 Egon = Person(name="Egon", age=9000) Eva_J = Person(name="Eva_J", age=18) person_list = [Alex, Egon, Eva_J] return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
return render(request,'template_test.html',locals())
locals() 获取函数内容所有变量,然后通过reader方法给了template_test.html文件进行模板渲染,省事就可以用,但效率低
模板支持的写法
{# 取l中的第一个参数 #} {{ l.0 }} {# 取字典中key的值 #} {{ d.name }} {# 取对象的name属性 #} {{ person_list.0.name }} {# .操作只能调用不带参数的方法 #} {{ person_list.0.dream }}
过滤器
在Django的模板语言中,通过使用 过滤器 来改变变量的显示。
过滤器的语法: {{ value|filter_name:参数 }}
使用管道符"|"来应用过滤器。
例如:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。
注意事项:
- 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
- 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
- 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
- '|'左右没有空格,有空格不显示效果
Django的模板大约有60个内置过滤器
filters
语法{{value|filter_name:参数}}
default
如果value值没传的话就显示nothing
{{ value|default: "nothing"}}
length
返回value的长度
{{ value|length }} 注:‘|’左右没有空格
filesizefomat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。
{{ value|filesizeformat }}
slice
切片,对字符串进行切片
{{value|slice:"2:-1"}}
date
格式化,如value = datatime.datetime.now()
{{ value|date:"Y-m-d H:i:s"}}
safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
{{ value|safe}}
truncatechars
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数
{{ value|truncatechars:9}} #三个省略号也包括在内
truncatewords
在一定数量的字后载断字符串,是载取多少个单词
如 ''I Iove you , my girl I''
{{value|truncatewords:3}} #上面例子结果 ''I Iove you...'
cut
移除value中所有的与给出的变量相同的字符串
{{value|cut:' '}} #移除空行
jion
使用字符串连接列表
{{value|join:','}} #跟python的str.join很像
自定义filter
自定义过滤器只是带有一个或两个参数的Python函数:变量跟参数值
在app01目录下创建templateags文件夹,然后在文件夹中自定义app01_filters.py文件(文件名自定义)
编写自定义filter
from django import template register = template.Library() # 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫sb @register.filter(name="sb") def add_sb(arg): return "{} sb.".format(arg) # 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫addstr @register.filter(name="addstr") def add_str(arg, arg2): """ 第一个参数永远是管道符前面那个变量 :param arg: 道符前面那个变量 :param arg2: 冒号后面的变量 :return: """ return "{} {}.".format(arg, arg2)
使用自定义filter
{# 先导入我们自定义filter那个文件 #} {% load app01_filters %} {# 使用我们自定义的filter #} {{ somevariable|cut:"0" }} {{ d.name|addstr }}
Tags标签
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...
标签 内容 ... {% endtag %})。
for标签
遍历每一个元素: 写个for,然后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,你要通过js
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul>
变量字典
{% for key,val in dic.items %} <p>{{key}}:{{val}}</p> {% endfor %}
其他循环号
forloop.counter //当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能 forloop.counter0 // 当前循环的索引值(从0开始) forloop.revcounter // 当前循环的倒序索引值(从1开始) forloop.revcounter0 //当前循环的倒序索引值(从0开始) forloop.first //当前循环是不是第一次循环(布尔值)返回False forloop.last //当前循环是不是最后一次循环(布尔值)返回False forloop.parentloop // 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
for ... empty
for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空空如也</li> {% endfor %} </ul>
if标签
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
if,elif,else
{% if p3 %} <p>p3:{{ p3 }}</p> {% elif p2 %} <p>p2:{{ p2 }}</p> {% else %} <p>什么人都没有!</p> {% endif %}
if else
{% if name_list|length >= 3 %} <p>需要打两辆车</p> {% else %} <p>一辆足矣!</p> {% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with
使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
<p>with语句</p> {{ name_list2.1.1 }} {% with name=name_list2.1.1 %} {{ name }} {% endwith %}
或者
{% with name_list2.1.1 as name %}
{{ name }}
{% endwith %}
csrf_token
这个标签用于跨站请求伪造保护。
注意是在form表单里面
在页面的form表单里面写上{% csrf_token %}
爬虫发送post请求模拟
import requests res = requests.post('http://127.0.0.1:8000/login/',data={ 'username':'qian', 'password':'123' }) print(res.text)
注释
{# ... #}
注意事项
Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %} ... {% endif %}
如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:默认会取d的items key的值。
{{ data.items }}
模板继承
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} 母板的title信息 {% endblock %} </title> <style> body{ padding:0; margin: 0; } .nav{ background-color:red; height: 40px; } .left_list div{ width: 100px; height: 20px; background-color:pink; border-bottom:1px solid black; } .left_list{ float:left; width: 100px; } .content{ float:right; width:600px; height:100px; } </style> </head> <body> <div class="nav"><a href="">新闻</a><a href="">视频</a><a href="">图片</a></div> <div class="left_list"> {% block list %} <div><a href="/index/">首页</a></div> <div><a href="/order/">订单页</a></div> <div><a href="/user/">个人中心</a></div> {% endblock %} </div> <div class="content"> {% block content %} 模板预留的地方 {% endblock %} </div> </body> </html>
这个模版,我们把它叫作 base.html
, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。
在这个例子中, block
标签定义了三个可以被子模版内容填充的block。 block
告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。
子模版index.html可能看起来是这样的:
{% extends 'base.html' %} {% block title %} 首页 {% endblock %} {% block content %} <a href="">首页</a> <span>首页介绍</span> {{ block.super }} #继承父类的模板内容 {% endblock %}
extends
标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。
- block标签中的名字是自己起的
- 不能在一个模版中定义多个相同名字的
block
标签
组件
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。
{% include 'nav.index' %}
导航栏 nav.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .c1{ background-color: red; height: 40px; } </style> </head> <body> <div class="c1"> <div> <a href="">alex</a> <a href="">wusir</a> </div> </div> </body> </html>
嵌入导航栏页面 test.hrml
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'nav.html' %} <h1>哈喽</h1> </body> </html>
自定义标签和过滤器
在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
在app中创建templatetags模块(模块名只能是templatetags)
创建任意 .py 文件,如:my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library() # register的名字是固定的,不可改变 @register.filter def filter_multi(v1, v2): return v1.replace('o', v2) @register.simple_tag # 和自定义filter类似,只不过接收更灵活的参数,没有个数限制。 def simple_tag_multi(v1, v2): return v1 * v2
在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py
{% load my_tags %}
home.html
{% load my_tags %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ date|date:'Y-m-d' }} {{ name|filter_multi:'xxx'}} {% simple_tag_multi 2 4 %} {% my_input 2 'c1' %} </body> </html>
views.py
imput datetime
def home(request):
return render(request,'home.html',{'date':datetime.datetime.now(),
'name':'hello','age':'18'})
注意:filter可以用在if、for等语句后,simple_tag不可以
inclusion_tag
用于返回html代码片段
my_inclusin.py
from django import template register = template.Library() @register.inclusion_tag('result.html') #将result.html里面的内容用下面函数的返回值渲染,然后作为一个组件一样,加载到使用这个函数的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}#这里可以穿多个值,和render的感觉是一样的{'data1':data1,'data2':data2....}
home.html
{% load my_inclusion %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for choice in data %} <li>{{ choice }}</li> {% endfor %} </ul> </body> </html>
index.html
{% load my_inclusion %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% show_results 10 %} </body> </html>
静态文件配置
js、css、img等都叫做静态文件,那么关于django中静态文件的配置,我们就需要在settings配置文件里面写上这写内容
STATIC_URL = '/static/' #别名 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'statics'), #注意别忘了写逗号,第二个参数就是项目中你存放静态文件的文件夹名称 ]
文件导入到html中的方式
img目录
{% load static %} <img src="{% static "imgs/hi.jpg" %}" alt="Hi!" />
js目录
{% load static %} <script src="{% static "mytest.js" %}"></script>