Django模板语言
Django模板系统
常用语法
{{ 变量名 }} 和 {% 变量名 %}
变量相关的用{{ 变量名 }},逻辑相关的用{% 变量名 %}
变量
在Django的模板语言中按此语法使用:{{ 变量名 }}。
当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。
点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:
字典查询(Dictionary lookup)
属性或方法查询(Attribute or method lookup)
数字索引查询(Numeric index lookup)
注意事项: |
案例
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^template_test/', views.template_test),
]
views.py
from django.shortcuts import render
# Create your views here.
def template_test(request):
ls = [11, 21, 22]
dic = {'name': '魏新雨咋软'}
class Person(object):
def __init__(self, name, age, dream):
self.name = name
self.age = age
self.dream = dream
def dream(self):
return '{}的梦想是成为一个摄影师'.format(self.name)
weixinyu = Person('魏新雨', 33, '魏新雨咋软')
chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')
return render(request, 'template_test.html', locals())
/templates/template_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-Type" 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>
</head>
<body>
<h1>列表</h1>
{{ ls }}
<br>
<h2>取列表的索引</h2>
{{ ls.0 }}
{{ ls.1 }}
{{ ls.2 }}
<br>
<h1>字典</h1>
{{ dic }}
<br>
<h2>取字典的value</h2>
{{ dic.name }}
<br>
<h1>对象</h1>
<p>{{ weixinyu.name }}: 字 {{ weixinyu.dream }}</p>
<p>{{ chenjun.name }}: 字 {{ chenjun.dream }}</p>
</body>
</html>
Filters(过滤器)
在Django的模板语言中,通过使用 过滤器 来改变变量的显示。
过滤器的语法:
{{ value|filter_name:参数 }}
使用管道符|
来应用过滤器。
例如:{{ name|lower }}
会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。
注意事项:
1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
2. 过滤器可以接受参数,例如:`{{ sss|truncatewords:30 }}`,这将显示sss的前30个单词。
3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:`{{ list|join:', ' }}`
4. "|" 左右没有空格没有空格没有空格
### lower
将字符串转换成小写
{{ name2|lower }}
join
使用字符串连接列表,例如Python的str.join(list)
{{ ls|join:'-' }}
### default
设置默认值
{{ s14|default:'s14这个变量是个空值' }}
lenth
计算数据的长度
{{ ls|length }}
filesizeformat
将数值换成人类易读的文件的单位
{{ file_size|filesizeformat }}
### slice
切片
{{ name2|slice:'1:-1' }}
{{ name2|slice:'1:-1:2' }}
data
指定时间格式
{{ now|date:'Y-m-d H:i:s' }}
timesince
变量的时间距离现在的时间多久了, 变量的时间必须是过去的时间
{{ comment_date|timesince }}
timeuntil
现在距离变量的时间距离还有多久, 变量的时间必须是未来的时间
{{ from_date|timeuntil }}
### safe
将html字符串在浏览器渲染成html格式的数据(取消对html标签的转义)
{{ html|safe }}
truncatechars
如果截取的数量小于文本数量, 则最后三个字符会用...表示
{{ s1|truncatechars:5 }}
truncatewords
截取单词, 通过空格来区分单词, 如果截取的字符数小于数据的总长度, 则剩下的字符数用...来代替
{{ s1|truncatewords:7}}
cut
移除value中所有的与给出的变量相同的字符串
{{ s2|cut:' ' }}
divisibleby
如果value可以被给出的参数整除,则返回 True
{{ value|divisibleby:“2” }}
<p>{{ 4|divisibleby:'2' }}</p>
<p>{{ 3|divisibleby:'2' }} </p>
### **自定义filter**
定义
1. 在app目录下创建一个名为 templatetags 的python包
2. 在上面创建的包内部创建一个python文件: filter.py
3. 在filter.py文件中按照固定的格式注册的一个自定义的filter
from django import template
# 固定写法, 生成一个注册实例对象
register = template.Library()
@register.filter(name='generator_sb') # 告诉django的模板语言, 现在注册一个自定义的filter, name属性则是指定模板语言调用它时候用的名字, 默认不指定是用函数名
def add_sb(value):
'''
给任意指定的变量添加sb
:param value: | 左边被修饰的那个变量
:return: 修饰后的内容
'''
return value + 'sb'
@register.filter()
def add_str(value, arg):
return value + arg
使用
1. 重启Django项目
2. 在HTML页面中:{% load python文件名 %}
3. {{ name2|add_str:'大好人' }}
设置默认时间的显示格式
settings.py
USE_L10N = False
DATETIME_FORMAT = 'Y-m-d H:i:s'
{{ now }}
Tags(标签)
views.py
def template_test(request):
ls = [11, 21, 22]
dic = {'name': '魏新雨咋软'}
name2 = 'WEI XINYU ZARUAN'
file_size = 84987394875739397459
now = datetime.datetime.now()
html = '<a href="https://www.baidu.com">百度一下</a>'
s1 = '世情薄人情恶雨送黄昏花易落'
s2 = "Hello, man, how are you? thank you. And you"
comment_date = now - datetime.timedelta(days=7)
from_date = now + datetime.timedelta(days=7)
lis = [
['魏新雨咋软', '陈骏啊, 萨宁啊', '傻人', '魏新雨咋软不累赛了'],
['魏新雨咋软2', '陈骏啊2, 萨宁啊2', '傻人2', '魏新雨咋软不累赛了2'],
['魏新雨咋软3', '陈骏啊3, 萨宁啊2', '傻人3', '魏新雨咋软不累赛了3'],
['魏新雨咋软4', '陈骏啊4, 萨宁啊2', '傻人4', '魏新雨咋软不累赛了4'],
]
class Person(object):
def __init__(self, name, age, dream):
self.name = name
self.age = age
self.dream = dream
def dream(self):
return '{}的梦想是成为一个摄影师'.format(self.name)
weixinyu = Person('魏新雨', 33, '魏新雨咋软')
chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')
# return render(request, 'template_test.html', locals())
return render(request, 'index.html', locals())
需求1 偶数列变色
index.html
<table border="1px">
<thead></thead>
<tbody>
{% for row in lis %}
<tr>
{% for name in row %}
{% if forloop.counter|divisibleby:'2' %}
<td style="color: green">{{ name }}</td>
{% else %}
<td>{{ name }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
需求2 偶数行变色
<table border="1px">
<thead></thead>
<tbody>
{% for row in lis %}
<tr>
{% for name in row %}
{% if forloop.parentloop.counter|divisibleby:'2' %}
<td style="color: green">{{ name }}</td>
{% else %}
<td>{{ name }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
偶数行偶数列变色
<table border="1px">
<thead></thead>
<tbody>
{% for row in lis %}
<tr>
{% for name in row %}
{% if forloop.parentloop.counter|divisibleby:'2' and forloop.counter|divisibleby:'2' %}
<td style="color: green">{{ name }}</td>
{% else %}
<td>{{ name }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
注意
模板语言不支持链式比较, 出现链式比较的时候, 比如说 a>b>c, 则会先计算a>b是True还是False, 然后在用0或者1与c再进行比较
{% if 2 > 1 == 1 %}
这是真的
{% else %}
这是假的
{% endif %}
输出结果
这是真的
{% if 2 > 1 > 1 %}
这是真的
{% else %}
这是假的
{% endif %}
输出结果
这是假的
if
{% if 条件%}
操作
{% endif %}
{% if 条件%}
操作
{% elif 条件 %}
{% else %}
{% endif %}
注意:
1. 不支持连续判断 a>b>c a>b and b>c
2. 不支持算数运算 + - * / add
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 |
本层循环的外层循环 |
with
{% with 变量 as 别名%}
{{ 别名 }}
{% endwith %}
Csrf token
1. 放在form表单中
2. 在表单中添加了一个隐藏的input标签
name csrfmiddlewaretoken
valve askjdaskdhashdkasd 64
<input type="hidden" name="csrfmiddlewaretoken" value="2V2pQjIqT0ZDkSImSguofhdLRKAUPyIvZk7zLjzgtNgyna7gdGmoWjF1Rv7UuOBI">
自定义simpletag
/templatetags/simlpletag.py
from django import template
register = template.Library()
@register.simple_tag
def join_str(*args, **kwargs):
print(args)
print(kwargs)
if args and not kwargs:
return "_".join(args)
if kwargs and not args:
return "_".join((kwargs['k1'], kwargs['k2']))
if kwargs and args:
args_list = list(args)
args_list.extend([kwargs.get('k1'), kwargs.get('k2')])
return "_".join(args_list)
views.py
def template_test(request):
ls = [11, 21, 22]
dic = {'name': '魏新雨咋软'}
name2 = 'WEI XINYU ZARUAN'
file_size = 84987394875739397459
now = datetime.datetime.now()
html = '<a href="https://www.baidu.com">百度一下</a>'
s1 = '世情薄人情恶雨送黄昏花易落'
s2 = "Hello, man, how are you? thank you. And you"
comment_date = now - datetime.timedelta(days=7)
from_date = now + datetime.timedelta(days=7)
lis = [
['魏新雨咋软', '陈骏啊, 萨宁啊', '傻人', '魏新雨咋软不累赛了'],
['魏新雨咋软2', '陈骏啊2, 萨宁啊2', '傻人2', '魏新雨咋软不累赛了2'],
['魏新雨咋软3', '陈骏啊3, 萨宁啊2', '傻人3', '魏新雨咋软不累赛了3'],
['魏新雨咋软4', '陈骏啊4, 萨宁啊2', '傻人4', '魏新雨咋软不累赛了4'],
]
class Person(object):
def __init__(self, name, age, dream):
self.name = name
self.age = age
self.dream = dream
def dream(self):
return '{}的梦想是成为一个摄影师'.format(self.name)
weixinyu = Person('魏新雨', 33, '魏新雨咋软')
chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')
# return render(request, 'template_test.html', locals())
return render(request, 'index.html', locals())
index.html
<h2>自定义simple_tag</h2>
{% load simlpletag %}
{% join_str '魏新雨' '咋软' '是' '个' '大好人' k1='魏新雨' k2='咋软'%}
### 自定义inclusion_tag
多用于返回html代码片段
1. 在app下创建一个templatetags的python包 templatetags名字不能错
2. 在包下写py文件 mypaginator
3. 编辑文件
4. 定义函数
可以接受参数
返回一个字典
5. 函数上加装饰器 ---> @register.inclusion_tag('mypaginator.html')
from django import template
register = template.Library()
@register.inclusion_tag('mypaginator.html')
def mypaginator(total, current_num):
total = range(1, total+1)
current_num = current_num
return locals()
6. 函数返回的字典 交给 pagination.html 渲染
<!--分页开始-->
<div>
<nav aria-label="Page navigation" class="pull-right">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% for num in total %}
{% if num == current_num %}
<li class="active"><a href="#">{{ num }}</a></li>
{% else %}
<li><a href="#">{{ num }}</a></li>
{% endif %}
{% endfor %}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<!--分页结束-->
母版
<!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块,方便子页面替换
继承母板
{% extends 'layouts.html' %}
块(block)
通过在母板中使用{% block xxx %}来定义"块"
在子页面中通过定义母板中的block名来对应替换母板中相应的内容
{% block page-main %}
<p>世情薄</p>
<p>人情恶</p>
<p>雨送黄昏花易落</p>
{% endblock %}
组件
1. 写一段的代码 nav.html
2. {% include 'nav.html' %}
静态文件相关
1. {% load static %}
static 是个变量, 会获取settings中获取STATIC_URL的值
2. {% static '相对路径' %} ——》 去settings中获取STATIC_URL '/alias/' 和相对路径进行拼接
<link href="{% static "bootstrap-3.3.7/css/bootstrap.css" %}" rel="stylesheet">
3. {% get_static_prefix %} ——》 去settings中获取STATIC_URL '/alias/'
"{% get_static_prefix %}相对路径"
<link href="{% get_static_prefix %}dashboard.css" rel="stylesheet">