Django模板层
后端向前端模板层发送数据的两种方式
第一种直接发送字典的形式:
后端view视图函数层
def index(request):
name = 'ZhaoKang'
return render(request,'index.html',{'name':name})
前端模板层:
<p>{{ name }}</p> # 注意前端要拿后端发送过来的数据的时候一定要用{{}}来接收 然后取字典的键就可以拿出值
后端view视图函数层
def index(request):
name = 'ZhaoKang'
return render(request,'index.html',{'name':name})
前端模板层:
<p>{{ name }}</p> # 注意前端要拿后端发送过来的数据的时候一定要用{{}}来接收 然后取字典的键就可以拿出值
方式二locals():
# locals() 将当前所在的名称空间中的名字全部传递给前端页面
后端view视图层
def index(request):
name = 'ZhaoKang'
return render(request,'index.html',locals())
前端模板层
<p>{{ name }}</p>
# locals() 将当前所在的名称空间中的名字全部传递给前端页面
后端view视图层
def index(request):
name = 'ZhaoKang'
return render(request,'index.html',locals())
前端模板层
<p>{{ name }}</p>
不知道你们有没有发现,我上面传的是字符串类型,既然我上面传的是字符串类型不防试试,数字类型(整型和浮点型),列表,字典,元祖,集合,函数,类,看看能不能传到前端?
后端视图层
def index(request):
name = 'ZhaoKang'
age = 18
salary = 16000.666
l = [1,3.14,'zk',[1,2,3],{'name':'zk'},(1,2),{3,4}]
dic = {'name':'zhaokang','age':18}
t = (1,2)
s = {1,2,3,4}
def func():
print(111)
class C(object):
def __init__(self,name):
self.name = name
def index(self):
return self.name
@classmethod
def func(cls):
return cls
obj = C('zhaokang')
print(obj)
return render(request,'index.html',locals())
前端模板层
<p>{{ name }}</p> # ZhaoKang
<p>{{ age }}</p> # 18
<p>{{ salary }}</p> # 16000.666
<p>{{ l }}</p> # [1, 3.14, 'zk', [1, 2, 3], {'name': 'zk'}, (1, 2), {3, 4}]
<p>{{ dic }}</p> # {'name': 'zhaokang', 'age': 18}
<p>{{ t }}</p> # (1, 2)
<p>{{ s }}</p> # {1, 2, 3, 4}
<p>{{ func }}</p> # None
<p>{{ obj }}</p> # <app01.views.index.<locals>.C object at 0x04178D90>
后端视图层
def index(request):
name = 'ZhaoKang'
age = 18
salary = 16000.666
l = [1,3.14,'zk',[1,2,3],{'name':'zk'},(1,2),{3,4}]
dic = {'name':'zhaokang','age':18}
t = (1,2)
s = {1,2,3,4}
def func():
print(111)
class C(object):
def __init__(self,name):
self.name = name
def index(self):
return self.name
@classmethod
def func(cls):
return cls
obj = C('zhaokang')
print(obj)
return render(request,'index.html',locals())
前端模板层
<p>{{ name }}</p> # ZhaoKang
<p>{{ age }}</p> # 18
<p>{{ salary }}</p> # 16000.666
<p>{{ l }}</p> # [1, 3.14, 'zk', [1, 2, 3], {'name': 'zk'}, (1, 2), {3, 4}]
<p>{{ dic }}</p> # {'name': 'zhaokang', 'age': 18}
<p>{{ t }}</p> # (1, 2)
<p>{{ s }}</p> # {1, 2, 3, 4}
<p>{{ func }}</p> # None
<p>{{ obj }}</p> # <app01.views.index.<locals>.C object at 0x04178D90>
各种数据类型以及函数,类,都是可以完成传值的,但是有几点问题
第一:为什么函数拿到的结果是None,函数不是在被加括号的时候才能执行函数体内的代码吗,这里我单独拿出来试试。
后端view层
def func():
return '你调用了我'
前端模板层
<p>{{ func }}</p> # 你调用了我
后端view层
def func():
return '你调用了我'
前端模板层
<p>{{ func }}</p> # 你调用了我
有没有发现这里返回的是“你调用了我”,所以这里可以得出结论是:后端传函数名到前端,会自动加括号调用,且拿到的是函数的返回值。
注意:后端传函数名到前端,会自动加括号调用,但是不支持传参,如果不行不防可以试试。
第二:为什么后端传对象到前端只能拿到一个内存地址呢?
因为后端传对象到前端的时候自动会帮你打印这个对象。
还可以通过对象点的方式拿到类里面的属性和方法,你信你试试
<p>{{ obj.name }}</p> # zhaokang
<p>{{ obj.func }}</p> # <class 'app01.views.index.<locals>.C'>
<p>{{ obj.index }}</p> # zhaokang
<p>{{ obj.name }}</p> # zhaokang
<p>{{ obj.func }}</p> # <class 'app01.views.index.<locals>.C'>
<p>{{ obj.index }}</p> # zhaokang
第三我列表,字典,元祖,集合,里面有多个值我怎么获取到里面的某个值呢。
<p>{{ l.0 }}</p> # 拿到的就是列表的第一个元素就相当于索引取值
<p>{{ t }}</p> # 元祖也是一样通过 点索引的方式
<p>{{ s }}</p> # 集合也是一样通过 点索引的方式
<p>{{ dic.name }}</p> # 几点可以通过点它的键的方式来获取它的值
<p>{{ l.0 }}</p> # 拿到的就是列表的第一个元素就相当于索引取值
<p>{{ t }}</p> # 元祖也是一样通过 点索引的方式
<p>{{ s }}</p> # 集合也是一样通过 点索引的方式
<p>{{ dic.name }}</p> # 几点可以通过点它的键的方式来获取它的值
补充:字符串,列表,字典,元祖,集合可以点出所有的内置方法的,不是所有的方法都是在前端可以用的,只有那些不需要传参的内置方法才可以实现,比如字典 values(),items(),keys()
过滤器:
<p>前端统计字符串的长度:{{ l|length }}</p> <!--结果为7-->
flag = None # 我后端给flag设置值为None
<p>前端获取数据如果是空就返回default后面默认的参数值:{{ flag|default:'你这个东西是个空'}}</p>
<p>将数字格式化成表示文件大小的单位:{{ file_size|filesizeformat }}</p>
<p>格式化时间(不要加百分号){{ ctime|date:'Y-m-d' }}</p>
<p>字符串的切片操作:{{ res|slice:'0:8' }}</p>
<p>{{ res|slice:'0:8:2' }}</p> 从0开始到7个字符且步长为2 相当于python中的切片顾头不顾尾
<p>截取固定的长度的字符串 三个点也算:{{ res|truncatechars:10 }}</p>
<p>按照空格截取文本内容:{{ res|truncatewords:4 }}</p>
<p>前端统计字符串的长度:{{ l|length }}</p> <!--结果为7-->
flag = None # 我后端给flag设置值为None
<p>前端获取数据如果是空就返回default后面默认的参数值:{{ flag|default:'你这个东西是个空'}}</p>
<p>将数字格式化成表示文件大小的单位:{{ file_size|filesizeformat }}</p>
<p>格式化时间(不要加百分号){{ ctime|date:'Y-m-d' }}</p>
<p>字符串的切片操作:{{ res|slice:'0:8' }}</p>
<p>{{ res|slice:'0:8:2' }}</p> 从0开始到7个字符且步长为2 相当于python中的切片顾头不顾尾
<p>截取固定的长度的字符串 三个点也算:{{ res|truncatechars:10 }}</p>
<p>按照空格截取文本内容:{{ res|truncatewords:4 }}</p>
过滤器 | 描述 | 示例 |
upper | 以大写方式输出 | {{ user.name | upper }} |
add | 给value加上一个数值 | {{ user.age | add:”5” }} |
addslashes | 单引号加上转义号 | |
capfirst | 第一个字母大写 | {{ ‘good’| capfirst }} 返回”Good” |
center | 输出指定长度的字符串,把变量居中 | {{ “abcd”| center:”50” }} |
cut | 删除指定字符串 | {{ “You are not a Englishman” | cut:”not” }} |
date | 格式化日期 | |
default | 如果值不存在,则使用默认值代替 | {{ value | default:”(N/A)” }} |
default_if_none | 如果值为None, 则使用默认值代替 | |
dictsort | 按某字段排序,变量必须是一个dictionary | {% for moment in moments | dictsort:”id” %} |
dictsortreversed | 按某字段倒序排序,变量必须是dictionary | |
divisibleby | 判断是否可以被数字整除 |
|
escape | 按HTML转义,比如将”<”转换为”<” | |
filesizeformat | 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 |
|
first | 返回列表的第1个元素,变量必须是一个列表 | |
floatformat | 转换为指定精度的小数,默认保留1位小数 | {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入 |
get_digit | 从个位数开始截取指定位置的数字 | {{ 123456 | get_digit:’1’}} |
join | 用指定分隔符连接列表 | {{ [‘abc’,’45’] | join:’’ }} 返回 abc45 |
length | 返回列表中元素的个数或字符串长度 | |
length_is | 检查列表,字符串长度是否符合指定的值 | {{ ‘hello’| length_is:’3’ }} |
linebreaks | 用 或 | {{ “Hi\n\nDavid”|linebreaks }} 返回 Hi David |
linebreaksbr | 用 标签代替换行符 | |
linenumbers | 为变量中的每一行加上行号 | |
ljust | 输出指定长度的字符串,变量左对齐 | {{‘ab’|ljust:5}}返回 ‘ab ’ |
lower | 字符串变小写 | |
make_list | 将字符串转换为列表 | |
pluralize | 根据数字确定是否输出英文复数符号 | |
random | 返回列表的随机一项 | |
removetags | 删除字符串中指定的HTML标记 | {{value | removetags: “h1 h2”}} |
rjust | 输出指定长度的字符串,变量右对齐 | |
slice | 切片操作, 返回列表 | {{[3,9,1] | slice:’:2’}} 返回 [3,9] |
slugify | 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 |
|
stringformat | 字符串格式化,语法同python | |
time | 返回日期的时间部分 | |
timesince | 以“到现在为止过了多长时间”显示时间变量 | 结果可能为 45days, 3 hours |
timeuntil | 以“从现在开始到时间变量”还有多长时间显示时间变量 | |
title | 每个单词首字母大写 | |
truncatewords | 将字符串转换为省略表达方式 |
|
truncatewords_html | 同上,但保留其中的HTML标签 |
|
urlencode | 将字符串中的特殊字符转换为url兼容表达方式 | {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} |
urlize | 将变量字符串中的url由纯文本变为链接 | |
wordcount | 返回变量字符串中的单词数 | |
yesno | 将布尔变量转换为字符串yes, no 或maybe |
|
转义和取消转义:
当我们在后台写一串字符串的写的是前端html的标签,然后在发送给前端这时我们会发现得到的根本不是我们想要的,如果我们写一段html标签前面也展示出来了,那就意味着别人就可以实现脚本攻击,对你的网站进行攻击。
后端
def index(request):
s = '<p>苍茫的天涯是我的爱</p>'
return render(request,'index.html',locals())
前端
{{ s }} # 打印结果是:<p>苍茫的天涯是我的爱</p>
后端
def index(request):
s = '<p>苍茫的天涯是我的爱</p>'
return render(request,'index.html',locals())
前端
{{ s }} # 打印结果是:<p>苍茫的天涯是我的爱</p>
如果我就是想要我后端发一段前端html的代码前端就显示出,那怎么办呢,可以通过safe来实现?
前端实现方式
{{ s|safe }} <!--结果就是带段落标签的一段话了-->
后端实现方式
作为调包侠肯定想到的就是调包啊
from django.utils.safestring import mark_safe
s = mark_safe('<p>苍茫的天涯是我的爱</p>')
前端实现方式
{{ s|safe }} <!--结果就是带段落标签的一段话了-->
后端实现方式
作为调包侠肯定想到的就是调包啊
from django.utils.safestring import mark_safe
s = mark_safe('<p>苍茫的天涯是我的爱</p>')
标签:
for循环
for循环
{% for foo in l %}
<p>{{ foo }}</p>
<p>{{ forloop }}</p>
{% endfor %}
for循环
{% for foo in l %}
<p>{{ foo }}</p>
<p>{{ forloop }}</p>
{% endfor %}
if判断
if判断
{% if flag %}
<p>flag不为空</p>
{% else %}
<p>flag是空</p>
{% endif %}
if判断
{% if flag %}
<p>flag不为空</p>
{% else %}
<p>flag是空</p>
{% endif %}
嵌套使用
{% for foo in l %}
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊</p>
{% else %}
<p>嗨起来!!!</p>
{% endif %}
{% endfor %}
{% for foo in l %}
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊</p>
{% else %}
<p>嗨起来!!!</p>
{% endif %}
{% endfor %}
empty
empty
当你的for循环对象为空的时候会自动走empty代码块儿的内容
后端:
l = None
前端:
{% for foo in l %}
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊</p>
{% else %}
<p>嗨起来!!!</p>
{% endif %}
{% empty %}
<p>你给我的容器类型是个空啊,没法for循环</p>
{% endfor %}
empty
当你的for循环对象为空的时候会自动走empty代码块儿的内容
后端:
l = None
前端:
{% for foo in l %}
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊</p>
{% else %}
<p>嗨起来!!!</p>
{% endif %}
{% empty %}
<p>你给我的容器类型是个空啊,没法for循环</p>
{% endfor %}
自定义过滤器:
必须做三件事情
1.在应用名下新建一个名为templates文件夹(必须叫这个名字)
2.在新建的文件夹内新建一个任意名称的py文件
3.在该py文件中需要固定写下面两句代码
from django import template
register = template.Library()
自定义过滤器
from django import template
from django.utils.safestring import mark_safe
register = template.Library() #register的名字是不可变的固定写法
@register.filter
def filter_multi(v1,v2):
return v1*v2
from django import template
from django.utils.safestring import mark_safe
register = template.Library() #register的名字是不可变的固定写法
@register.filter
def filter_multi(v1,v2):
return v1*v2
前端使用
{% load templatetags %}
{{ 2|filter_multi:6 }} # 得到的结果是12
{% load templatetags %}
{{ 2|filter_multi:6 }} # 得到的结果是12
注意:标签用在{%%}里面,过滤器用在{{}}里面
自定义标签:
后端
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # register的名字是不可变的固定写法
@register.simple_tag() # 这里可以给个name='' 去别名 前端用的话直接拿别名就可以了
def add1(a1,a2,a3):
return a1+a2+a3 # 一定要有返回值
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # register的名字是不可变的固定写法
@register.simple_tag() # 这里可以给个name='' 去别名 前端用的话直接拿别名就可以了
def add1(a1,a2,a3):
return a1+a2+a3 # 一定要有返回值
前端
{% add1 'zk' ' is' ' 很帅' %} 结果 zk is 很帅
{% add1 'zk' ' is' ' 很帅' %} 结果 zk is 很帅
注意:在你新定义一个标签过滤器一定要重新django项目不然会抛异常
标签是不能使用在if中的,而过滤器可以
过滤器
{% if 2|filter_multi:6 %}
<p>ok</p> 结果是ok
{% endif %}
标签
{% if add 'zk' 'is' '很帅' %} 这个地方直接就报错了
<p>ok</p>
{% endif %}
模板的导入:
1 模版导入-->写了一个好看的组件,可以复用,
1 写一个模板
2 在模板中:{% include '模板的名字'%}
2 模板的继承
1 写一个母版,留一个可扩展的区域(盒子),可以留多个盒子(留的越多,可扩展性越高)
{%block 名字%}
可以写内容
{%endblock%}
2 在子模板中使用:
{%block 名字%}
子模板的内容
{%endblock 名字%}
3 静态文件相关
1 写死静态文件:<link rel="stylesheet" href="/static/css/mycss.css">
2 使用 static标签函数:
-{%load static%}
#static返回值,会拼上传参的路径
-{% static "传参"%}
3 使用get_static_prefix 标签
-{%load static%}
#get_static_prefix返回值是:静态文件的地址,相当于/static/
-{% get_static_prefix %}css/mycss.css