• for循环---表格
views
def index(request):
context={
'books':[
{'name':'xiyouji','author':'k','price':99},
{'name':'hongloumeng','author':'j','price':90},
{'name':'shuihuzhuan','author':'a','price':106},
{'name':'sanguoyanyi','author':'b','price':112},
],
'person':{
'username':'Jim Green',
'age':20,
'sex':'man'
}
}
return render(request,'index.html',context=context)
html
<body>
......
<table>
<thead>
<tr>
<td>bookname</td> # 表头
<td>author</td> # 表格的基本格式就是这样
<td>price</td>
</tr>
</thead>
<tbody>
{% for book in books %} # 表身
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
效果:
bookname author price
xiyouji k 99
hongloumeng j 90
shuihuzhuan a 106
sanguoyanyi b 112
• forloop.counter---返回数值(循环的次数,从1开始,只能用于for循环)
forloop.counter0---从0开始计数
forloop.recounter---counter的倒序(比如counter是1-4,那么recounter就是4-1)
forloop.recounter0---倒序末位数是0
示例:
html
<body>
......
<table>
<thead>
<tr>
<td>number</td> # 添加计数
<td>bookname</td>
<td>author</td>
<td>price</td>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ forloop.counter }}</td> # forloop.counter计数
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
效果:
number bookname author price
1 xiyouji k 99
2 hongloumeng j 90
3 shuihuzhuan a 106
4 sanguoyanyi b 112
• forloop.first/last---对应 第一次/最后一次 循环
下述示例,对表格的第一行和最后一行渲染颜色:
<table>
<thead>
<tr>
<td>number</td>
<td>bookname</td>
<td>author</td>
<td>price</td>
</tr>
</thead>
<tbody>
{% for book in books %}
{% if forloop.first %} # 第一次循环,渲染样式
<tr style="background-color: green">
{% elif forloop.last %} # 最后一次循环,渲染样式
<tr style="background-color: brown">
{% else %}
<tr> # 如果不是第一次/最后一次,那么就返回普通标签
{% endif %}
<td>{{ forloop.counter }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
</tr> # 这个结束标签不能遗漏
{% endfor %}
</tbody>
</table>
看效果,成功渲染
• for...empty...示例:
views
from django.shortcuts import render
from django.template.loader import render_to_string
from django.http import HttpResponse
def index(request):
context={
'books':[
{'name':'sanguoyanyi','author':'shianang','price':100},
{'name':'shuihuzhuan','author':'luoguanz','price':120},
{'name':'hongloumeng','author':'caoxueqing','price':180},
{'name':'xiyouji','author':'wuchengen','price':200},
],
'person':{
'name':'Kate Green',
'age':18,
'sex':'woman',
},
'comments':[], # 这里只有为空,才会显示template的'There is no comment',值为None或者''都不行
}
#return render(request,'index.html',context=dict(person=p))
return render(request,'index.html',context=context)
{% for comment in comments %}
<p>{{ comment }}</p>
{% empty %}
<p>There is no any comment.</p>
{% endfor %}
• with用法:定义模板变量
<1>基础用法示例:
views
def index(request):
context={
......
'persons':[
'Jim Green',
'Kate Green',
'Li Lei',
'Han meimei',
],
}
return render(request,'index.html',context=context)
html
......
<body>
<p>{{ persons.0 }}</p> # 使用这种定义,显示'Jim Green'
<p>{{ persons.0 }}</p>
<p>{{ persons.0 }}</p>
</body>
现在换一种写法:
<body>
{% with name1=persons.0 %} # with相当于js的var,注意等号两边不能使用空格,否则语法错误
<p>{{ name1 }}</p> # 显示'Jim Green'
<p>{{ name1 }}</p>
<p>{{ name1 }}</p>
{% endwith %}
</body>
<2>使用as命名变量:
上述示例稍微调整一下:
<body>
{% with persons.0 as name1 %}
<p>{{ name1 }}</p> # 显示'Jim Green'
<p>{{ name1 }}</p>
<p>{{ name1 }}</p>
{% endwith %}
</body>
小结:具体使用哪种语法,看个人,我偏向于使用as;
使用with定义的变量,一旦范围超出'endwith',变量就失效了,这点要注意.
•spaceless标签:去除多余的空格,换行
示例:
{% spaceless %}
<p>
<a href="http://www.baidu.com">百度链接</a>
</p>
{% endspaceless %}
渲染后的效果(使用谷歌浏览器的'Sources'选项,而不是用'Elements'查看):
<p><a href="http://www.baidu.com">百度链接</a></p>
● 自动转义:django默认自动转义
示例:
views
def index(request):
context={
......
'info':"<a href='http://www.baidu.com'>百度链接</a>" # 注意这里的链接,只能用字符串来表示.
}
return render(request,'index.html',context=context)
html
{{ info }} # 效果:<a href='http://www.baidu.com'>百度链接</a>
源码:<a href='http://www.baidu.com'>百度链接</a> # 引号,破折号全被转义
现在,使用{% autoescape %}标签关闭/开启自动转义
html
{% autoescape off %}
{{ info }}
{% endautoescape %}
效果:成功实现链接的操作,而不会被转义成普通字符串.
• verbatim标签:包含在里面的'变量',不再表示'变量',它的作用就是可以和别的模板引擎混合使用
也就是说,可以把别的模板引擎语言,写在里面.
示例:
{% verbatim %}
{{ var }}
{% endverbatim %}
● url标签:反转网址,效果和view的reverse一样
示例:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Front index page</title>
<style>
.nav{
overflow: hidden; # <ul>标签使用样式
}
.nav li{ # <li>标签使用样式
float: left;
list-style: none;
margin: 0 20px;
}
</style>
</head>
<body>
<ul class="nav"> # 定义class属性,便于使用css样式
<li>首页</li>
<li>读书</li>
<li>电影</li>
<li>同城</li>
</ul>
</body>
</html>
views
def book(request):
return HttpResponse('读书页')
def movie(request):
return HttpResponse('电影页')
def city(request):
return HttpResponse('同城页')
urls
from django.contrib import admin
from django.urls import path
from front import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index),
path('book/',views.book,name='book'),
path('movie/',views.movie,name='movie'),
path('city/',views.city,name='city'),
]
启动服务,看看基本的效果,正常.
现在修改html文档,添加<a>标签链接:
<body>
<ul class="nav">
<li><a href="#">首页</a></li> # 这里href='/'也可以
<li><a href="{% url 'book' %}">读书</a></li> # 使用url标签做网址跳转
<li><a href="{% url 'movie' %}">电影</a></li>
<li><a href="{% url 'city' %}">同城</a></li>
</ul>
</body>
刷新一下,成功实现效果
• url标签接收url额外的参数示例:
views
...
def book_number(request,number):
text='The number of book_id is {}'.format(number)
return HttpResponse(text)
urls
...
path('book_detail/<number>',views.book_number,name='book_number'),
html
<body>
<ul class="nav">
<li><a href="#">首页</a></li>
<li><a href="{% url 'book' %}">读书</a></li>
<li><a href="{% url 'movie' %}">电影</a></li>
<li><a href="{% url 'city' %}">同城</a></li>
<li><a href="{% url 'book_number' number=6 %}">书籍编号</a></li> # 使用关键字参数来传递额外的值
</ul>
</body>
刷新效果,网址成功跳转
• url 查询字符串拼接(和reverse类似,也是采用拼接的方式)
示例:
views
def login(request):
keyword=request.GET.get('next')
if keyword:
text='登陆后跳转的url是{}'.format(keyword)
else:
text='next为空'
return HttpResponse(text)
urls
......
path('login/',views.login,name='login'),
html
<body>
<ul class="nav">
......
<li><a href="{% url 'book_number' number=6 %}">书籍编号</a></li>
<li><a href="{% url 'login' %}?next=">登陆</a></li> # 注意这种拼接的语法
</ul>
</body>
访问:http://127.0.0.1:8000/,点击'登陆'
跳转到:http://127.0.0.1:8000/login/?next= 网页显示'next为空'
现在给next赋值:<a href="{% url 'login' %}?next=用户的url">登陆</a>
跳转到:http://127.0.0.1:8000/login/?next=%E7%94%A8%E6%88%B7%E7%9A%84url,网页显示'登陆后跳转的url是用户的url'
复习之前的reverse()手动拼接url
def name(request):
query_string=request.GET.get('name')
if query_string:
text='Your name is {}'.format(query_string)
# 此时,若想获取当前url,只能手动拼接...
local_url=reverse('name')+'?name={}'.format(query_string) # /name/?name=JimGreen
print(local_url)
else:
text='Nothing'
return HttpResponse(text)
● DTL过滤器(函数)
• add过滤器:对传进来的值,进行'相加'或'拼接'操作
示例:
views
def index(request):
context={
'value':100 # 值为整型
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|add:200 }}</p> # 结果为300
</body>
源码:
def add(value, arg): # 接收的第一个参数是value
"""Add the arg to the value."""
try:
return int(value) + int(arg) # 优先进行整型计算
except (ValueError, TypeError):
try:
return value + arg # 否则就进行拼接
except Exception: # 如果拼接不成功,就返回空字符串
return ''
• cut过滤器:移除字符串中指定的值,类似于replace(args,' ')
示例:
views
def index(request):
context={
'value':'Jim Green',
}
html
<body>
<p>{{ value|cut:' ' }}</p> # JimGreen
</body>
• date过滤器:须传入datetime对象,再date转换成时间格式(具体的格式视需求而定)
示例:
views
from django.http import HttpResponse
from django.shortcuts import render
import datetime
def index(request):
context={
'today':datetime.datetime.now(),
}
return render(request,'index.html',context=context)
HTML
<p>{{ today|date:'Y-m-d' }}</p> # 2019-11-05
注意:datetime对象的默认形式,类似下面这样的,显然,不是我们想要的格式,故可以使用data过滤器达到想要效果格式:
from datetime import datetime
now=datetime.now()
now
datetime.datetime(2019, 12, 19, 14, 14, 30, 490242) # 类元组的格式吧...
date的其他参数,可以查阅官方文档进行修改
• default过滤器:若传入的value值为True,则返回该值,不做任何修改;若值为False,则返回default传入的值
示例:
views
def index(request):
context={
'value':'default值测试', # 若值为空list,则返回'计算为false'
}
html
<body>
<p>{{ value|default:'计算为false' }}</p> #返回 default值测试
</body>
default_if_none过滤器:仅仅只有值为None时,才渲染后面的值
示例:
views
def index(request):
context={
'value':None,
}
return render(request,'index.html',context=context)
html
<p>{{ value|default_if_none:'传入的值为None' }}</p> # 结果为:传入的值为None
• first/last过滤器:返回list,tuple,str的第一个/最后一个元素
示例:
views
def index(request):
context={
'value':['apple','pear','banana','noddle'],
}
return render(request,'index.html',context=context)
html
<p>{{ value|last }}</p> # noddle
<p>{{ value|first }}</p> # apple
• 对浮点数的位数进行限制---floatformat过滤器
示例:
views
def index(request):
context={
'value':63.8536,
}
return render(request,'index.html',context=context)
html
<p>{{ value|floatformat }}</p> # 63.9 不传参,默认只保留一个小数,四舍五入
<p>{{ value|floatformat:2 }}</p> # 63.85 保留两位小数,四舍五入
• join过滤器---对 list,str,tuple的元素进行拼接
示例:
views
def index(request):
context={
'value':[1,2,3,4]
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|join:'/' }}</p> # 1/2/3/4
</body>
• length过滤器---返回list,str,tuple的的长度(从1开始)
示例:
views
def index(request):
context={
'value':[1,2,3,4]
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|length }}</p> # 4
</body>
• lower(小写)/upper(大写)
示例:
views
def index(request):
context={
'value':'KING'
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|lower }}</p> # king
</body>
• random过滤器:随机从list,tuple,str选择一个元素
示例:
views
def index(request):
context={
'value':[1,2,3,4,5,6,7]
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|random }}</p> # 随机出现一个数字
</body>
• safe---相当于{% autoescape off %}
示例:
views
def index(request):
context={
'value':"<script>alert('Hello World')</script>"
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|safe }}</p> # 弹窗(说明js执行成功),这里若把safe省略,则会被自动转义成普通str
</body>
• slice---切片操作
示例:
views
def index(request):
context={
'value':[1,2,3,4,5,6]
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|slice:"3:5" }}</p> # [4,5] 切片从0开始
</body>
• striptags过滤器:去除value的html标签
示例:
views
def index(request):
context={
'value':"<script>alert('Hello World')</script>"
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|striptags }}</p> # alert('Hello World')
• truncatechars过滤器:如果给定的字符串长度超过了过滤器指定的长度。那么会进行切割,并且拼接三个点来作为省略号
注意:三个点也算在指定的长度里面,算三个字符
示例:
views
def index(request):
context={
'value':"北京非常欢迎你"
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|truncatechars:"5" }}</p> # 北京...
'''
解析:value长度为7,超过过滤器指定的长度5,触发切割,留3个字符给'.'号,所以只能分配两个字符给'北京'
'''
</body>
html
<body>
<p>{{ value|truncatechars:"8" }}</p> # 北京非常欢迎你
'''
解析:value长度为7,没有超过过滤器指定的长度8,没有触发切割,所以原样返回'
'''
</body>
• truncatechars_html过滤器:同理;不同的地方,它不会计算html元素
示例:
views
def index(request):
context={
'value':"<p>北京非常欢迎你</p>"
}
return render(request,'index.html',context=context)
html
<body>
<p>{{ value|truncatechars_html:"5" }}</p> # <p>北京...</p>
</body>
● 自定义过滤器
<1>新建app并install_app
<2>app目录下,新建py包,并且一定命名为'templatetags'
<3>新建filename.py文件(例如'my_filters.py')
<4>导入注册模块,编写需要的功能
示例:
from django import template
register=template.Library()
'''
a) 自定义的函数,最多只能有两个参数
b) 第一个参数,永远是|左边的变量
'''
def join_together(value,word):
return value+' '+word
register.filter('join_together',join_together)
另一种写法---装饰器修饰
from django import template
register=template.Library()
@register.filter('join_to') # 这里若不传过滤器名称,则默认以'函数名称'作为'过滤器名称'
def join_together(value,word):
return value+' '+word
<5>view,html示例如下:
views
def index(request):
context={
'value':"Hello"
}
return render(request,'index.html',context=context)
html
{% load my_filter %} # 不能忘记加载刚才定义'my_filter.py'
<body>
<p>{{ value|join_together:'World' }}</p> # Hello World
</body>
★ 实际需求功能:有一个这样的值
时间1分钟以内---值就显示:刚刚
1m<x<60m---几分钟之前
1h<x<24h---几小时之前
1d<x<30d---几天前
x>30d---显示具体时间
my_filters.py
from django import template
from datetime import datetime
@register.filter()
def time_since(value): # value表示过去的时间
if not isinstance(value,datetime): # 对传入的值进行判断
return value
now=datetime.now() # 获取当前时间
timestamp=(now-value).total_seconds() # 获取时间差,用总秒数表示
if timestamp<60:
return '刚刚'
elif timestamp>=60 and timestamp<6060:
time=int(timestamp/60)
return '{} 分钟之前'.format(time)
elif timestamp>=6060 and timestamp<606024:
time=int(timestamp/60/60)
return '{} 小时之前'.format(time)
elif timestamp>=606024 and timestamp<606024*30:
time=int(timestamp/60/60/24)
return '{} 天之前'.format(time)
else:
return value.strftime("Y%-m%-d%-H%-M%") # 留意这种时间格式