一.Template概念
概念:模板
在Django框架中,模板是可以帮助开发者快速生成,呈现给用户页面的工具
模板的设计方式实现了我们MVT中VT的解耦,VT有着N:M的关系,一个V可以调用任意T,一个T可以供任意V使用
模板处理分为两个过程:加载、渲染
模板中的动态代码段除了做基本的静态填充,可以实现一些基本的运算,转换和逻辑。
早期的web服务器,只能处理静态资源请求,模板能处理动态资源请求,依据计算能生成相应的页面。
注意:在Django中使用的就是Django模板,在flask种使用的是jinja2模板
模板组成:模板主要有2个部分:
① HTML静态代码
② 动态插入的代码段(挖坑,填坑)
二.基本语法
1.变量
变量
视图传递给模板的数据
获取视图函数传递的数据使用{{ var }}接收
遵守标识符规则:
拒绝关键字、保留字、数字。。。如果变量不存在,则插入空字符串
来源:
视图中传递过来的
标签中,逻辑创建出来的
创建App,进行相关配置。
在TemApp中创建urls:
urlpatterns = [
url(r'^index/', views.index),
# 模板-变量
url(r'^testVar/', views.testVar),
]
在视图函数中添加:
def testVar(request):
# 使用上下文来传递数据
context = {
'name': 'yuan'
}
return render(request, 'testVar.html', context=context)
在templates中创建testVar.html文件,用来展示内容。
<body>
今天天气不错
{{ name }}
</body>
运行结果:
2.点语法
模板中的点语法用于属性或者方法。
创建路由:
url(r'^testPoint/',views.testPoint)
创建Animal模型
class Animal(models.Model):
name = models.CharField(max_length=32)
# 当使用模型对象调用getName的时候,那么返回的就是当前对象的name属性
# eg: a = Animal.object.first() a.getName就是a对象的名字
def getName(self):
return self.name
class Meta:
db_table = 'animal'
进行迁移,这里值得注意的是,需要在settings里INSTALLED_APPS中添加’TemApp’,不然会显示为No changes detected。
添加数据:
在视图函数中添加:
def testPoint(request):
a = Animal.objects.first()
hobby = {
'eat':'肉',
'play':'篮球'
}
animal_list = Animal.objects.all()
context = {
'a':a,
'hobby':hobby,
'animal_list':animal_list
}
return render(request,'testPoint.html',context=context)
创建testVar.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
比你聪明的人还在奋斗,怎能不努力!
{{ a.name }}
{{ a.getName }}
{{ hobby.play }}
{#找第二个动物#}
{{ animal_list.1.name }}
</body>
</html>
运行结果:
弊端:模板中的小弊端,调用对象的方法,不能传递参数。
为什么不能传递参数?因为连括号都没有。
2.标签
特征:标签分为单标签和双标签,其中双标签必须闭合。
(1)功能标签
for
创建路由:
url(r'^testTag/',views.testTag),
添加视图函数:
def testTag(request):
a_list = Animal.objects.all()
context = {
'a_list': a_list
}
return render(request, 'testTag.html', context=context)
创建testTag.html页面:
<body>
<ul>
{% for a in a_list %}
<li>{{ a.name }}</li>
{% endfor %}
</ul>
</body>
运行结果:
empty
添加empty标签会怎么样呢???
<body>
<ul>
{% for a in a_list %}
<li>{{ a.name }}</li>
{% empty %}
你好呀
{% endfor %}
</ul>
</body>
运行结果:
咦,没有变化,empty下面的文字也没显示。
当数据获取不到时:
<body>
<ul>
{% for a in a_list111 %}
<li>{{ a.name }}</li>
{% empty %}
你好呀
{% endfor %}
</ul>
</body>
运行结果:
empty会判断上面的数据是否可以获取到,如果获取到了,那么无所谓没有变化;如果获取不到,则显示empty下面的数据。
forloop:循环状态的记录
<body>
<ul>
{% for a in a_list1 %}
<li>{{ a.name }}</li>
{% empty %}
你好呀
{% endfor %}
</ul>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.counter }}
{% endfor %}
</ur>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.counter0 }}
{% endfor %}
</ur>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.revcounter }}
{% endfor %}
</ur>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.revcounter0 }}
{% endfor %}
</ur>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.first }}
{% endfor %}
</ur>
<hr>
<ur>
{% for a in a_list %}
{{ forloop.last }}
{% endfor %}
</ur>
</body>
运行结果:
{{ forloop.counter }} 表示当前是第几次循环,从1数数
{{ forloop.counter0}}表示当前是第几次循环,从0数数
{{ forloop.revcounter}}表示当前是第几次循环,倒着数数,到1停
{{ forloop.revcounter0}}表示当前第几次循环,倒着数,到0停
{{ forloop.first }} 是否是第一个 布尔值
{{ forloop.last }} 是否是最后一个 布尔值
if
{# 如果你是第一个数据 那么你就是绿色的 如果你是最后一个数据 你就是红色的#}
<ul>
{% for a in a_list %}
{% if forloop.first %}
<li style="color: #0b801a">{{ a.name }}</li>
{% elif forloop.last %}
<li style="color: #ff9c75">{{ a.name }}</li>
{% else %}
<li>{{ a.name }}</li>
{% endif %}
{% endfor %}
</ul>
运行结果:
(2)注释
在html中的注释主要有以下几种:
<!-- 这是一个注释,我知道你能看到-->
{# 我是一个单行注释,你看不到吧,气死你 #}
{% comment %}
我是一个多行注释
我写的再多,你也看不到,就是这么嚣张
{% endcomment %}
运行结果:
(3)withratio
乘
在testTag函数中添加:
def testTag(request):
a_list = Animal.objects.all()
num = 5
context = {
'a_list': a_list,
'num': num,
}
return render(request, 'testTag.html', context=context)
在testTag.html文件中添加:
{{ num }}
<br>
{# 分子在上面 分母在下面#}
{# widthratio 数 5/1#}
{# widthratio 数 分母 分子#}
{% widthratio num 1 5 %}
<br>
{% widthratio num 5 1 %}
运行结果:
(4)整除
整除可以应用于奇偶行变色
{# 奇偶行变色#}
<ul>
{% for a in a_list %}
{% if forloop.counter|divisibleby:2 %}
<li style="color: #0b801a">{{ a.name }}</li>
{% else %}
<li style="color: #782f80">{{ a.name }}</li>
{% endif %}
{% endfor %}
</ul>
运行结果:
(5)ifequal
ifequal与if有一样的效果
在testTag函数中添加:
def testTag(request):
a_list = Animal.objects.all()
num = 5
code = 10
context = {
'a_list': a_list,
'num': num,
'code': code,
}
return render(request, 'testTag.html', context=context)
在testTag.html文件中添加:
{% if code == 10 %}
11111
{% else %}
22222
{% endif %}
{% ifequal code 10 %}
33333
{% else %}
44444
{% endifequal %}
运行结果:
3.过滤器
创建过滤器模板:
url(r'^testFilter/',views.testFilter),
生成视图函数:
def testFilter(request):
context = {
'num': 10
}
return render(request, 'testFilter.html', context)
testFilter.html页面:
<body>
过滤器
<br>
{{ num }}
</body>
运行结果:
那么,怎么加10得到20呢???
我们正常的思维是不是以下几种方法呢,但是通过运行发现并不能得到20
{{ num + 10 }} # 会报错
{{ num }} + {{ num }} # 10+10
{{ num }} + 10 # 10+10
解决办法:
<body>
过滤器
<br>
{{ num|add:10 }}
</body>
运行结果:
那么如何减呢?
这里没有减,只有加一个负数:
<body>
过滤器
<br>
{{ num|add:10 }}
<br>
{{ num|add:-10 }}
</body>
运行结果:
如何将字母转换大小写呢?
def testFilter(request):
context = {
'num': 10,
'code': 'AsDfGhJk'
}
return render(request, 'testFilter.html', context)
html文件中:
<body>
过滤器
<br>
{{ num|add:10 }}
<br>
{{ num|add:-10 }}
<hr>
{{ code|lower }}
<br>
{{ code|upper }}
</body>
运行结果:
修改页面内容:
def testFilter(request):
# js脚本 修改页面中内容
code1 = '''
<script type="text/javascript">
var li_list = document.getElementsByTagName("li");
for(var i = 0;i < li_list.length; i++){
li_list[i].innerHTML = '努力';
}
</script>
'''
a_list = Animal.objects.all()
context = {
'num': 10,
'code': 'AsDfGhJk',
'a_list': a_list,
'code1': code1
}
return render(request, 'testFilter.html', context)
var li_list = document.getElementsByTagName(“li”):将找到整个文档中所有的li标签
<ul>
{% for a in a_list %}
<li>{{ a.name }}</li>
{% endfor %}
</ul>
{{ code1|safe }}
<hr>
运行结果:
autoescape与上面safe的效果一样,不同的是有开关功能,off生效、on失效:
{% autoescape off %}
{{ code1 }}
{% endautoescape %}
<hr>
{% autoescape on %}
{{ code1 }}
{% endautoescape %}
运行结果:
4.结构标签
如何继承一个模板呢???
创建结构标签模板:
url(r'^testCon/',views.testCon),
生成视图函数:
def testCon(request):
return render(request,'base.html')
创建base基本模板:
<head>
<meta charset="UTF-8">
<title>
{% block title %}
{% endblock %}
</title>
{% block ext_css %}
{% endblock %}
</head>
<body>
结构标签
{% block header %}
{% endblock %}
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
{% block ext_js %}
{% endblock %}
</body>
创建base_a.html模板:
{% extends 'base.html' %}
{% block header %}
源
{% endblock %}
视图函数:
def testCon(request):
return render(request,'base.html')
运行结果:
如何防止被覆盖???
创建base_b.html模板:
为避免被覆盖,使用block.super
{% extends 'base_a.html' %}
{% block content %}
源1
{% endblock %}
{% block header %}
{{ block.super }}
源2
{% endblock %}
视图函数:
def testCon(request):
return render(request,'base.html')
运行结果:
想要一个模板包含另一个模板,该怎么做呢?
创建base_c.html模板:
<ul>
<li>亚索</li>
<li>佐伊</li>
<li>厄斐琉斯</li>
</ul>
使base_b模板包含base_c模板:
{% extends 'base_a.html' %}
{% block content %}
源1
{% endblock %}
{% block header %}
{{ block.super }}
源2
{% endblock %}
{% block footer %}
{{ block.super }}
{% include 'base_c.html' %}
{% endblock %}
运行结果:
5.加载静态资源
创建加载静态资源的模板
url(r'^testStatic/',views.testStatic)
添加视图函数:
def testStatic(request):
return render(request,'testStatic.html')
创建testStatic.html模板:
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/testStatic.css">
</head>
<body>
<h4>加载静态资源</h4>
</body>
创建static文件夹,在其中创建testStatic.css文件以此来修改样式:
h4{
font-size: 50px;
color: red;
}
在settings文件中编辑:
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
运行结果:
上面使用的是硬编码,我们一般不推荐使用硬编码。
推荐以下写法:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'css/testStatic.css' %}">
</head>
<body>
<h4>加载静态资源</h4>
</body>
</html>
注意:仅在DEBUG模式下可以使用,如果settings中的DEBUG=False,那么是不可以使用的