Title

Django之模版层

模版层

模板语法符号
{{}} 变量相关
{%%} 逻辑相关

一.模版语法之传值

  • python基本数据类型全部支持传递给html文件
# views.py
def index(request):
    # python所有的数据类型都支持传递给html页面
    i = 11
    f = 11.11
    str = 'hello world'
    list = [1, 2, 3, 4, 5, 6]
    d = {"username": 'jason', 'password': 123, 'hobby': ['read', {'username': ['jason', 'egon']}]}
    t = (1, 2, 3, 4, 5, 6, 7,)
    se = {1, 2, 3, 4, 5, 6}
    b = True
    ff = False
    
	# python后端传给前端值的两种方式
    # 第一种传值方式
    return render(request, 'index.html', {'i':i, 'f':f, 'str': str })

# 第二种传值方式
    # 会将当前名称空间所有的变量名都全部传递给html页面
    return render(request, 'index.html', locals())

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ i }}</p>
<p>{{ f }}</p>
<p>{{ str }}</p>
<p>{{ list }}</p>
<p>{{ d }}</p>
<p>{{ t }}</p>
<p>{{ se }}</p>
<p>{{ b}}</p>
<p>{{ ff }}</p>
</body>

  • python后端函数发送到前端html页面
def index(request):
    # 写一个示例函数
    def func():
        print('views')
    return render(request, 'index.html', locals())
<!--这下面带#号的注释前端浏览器是不展示的,但是html自身的注释是可以看到的-->
{#<p>{{ i }}</p>#}
{#<p>{{ f }}</p>#}
{#<p>{{ str }}</p>#}
{#<p>{{ list }}</p>#}
{#<p>{{ d }}</p>#}
{#<p>{{ t }}</p>#}
{#<p>{{ se }}</p>#}
{#<p>{{ b}}</p>#}
{#<p>{{ ff }}</p>#}


<p>{{ func }}</p>

所以,当传递函数名的时候,函数名会自动加括号进行执行,展示的只是函数的返回值,若不设置返回值,默认返回None

注意:模板语法不支持给函数传参

  • python后端传递类给前端html页面
from django.shortcuts import render

def index(request):
    class MyClass(object):
        def get_self(self):
            return 'from self'
        
        @staticmethod
        def get_func():
            return 'from func'

        @classmethod
        def get_cls(cls):
            return 'from cls'

    obj = MyClass()
    return render(request, 'index.html', locals())
<p>{{ MyClass }}</p>
<p>{{ obj }}</p>

<body>
<p>{{ MyClass.get_cls }}</p>
<p>{{ MyClass.get_func }}</p>
<p>{{ MyClass.get_self }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func}}</p>
<p>{{ obj.get_self}}</p>
</body>
</html>

同样,传递类名给前端html时候的也会加括号执行获取类的对象,也不支持传参

  • 取值方法

django模板语法取值 只有一种操作方式 通过句点符 .

def index(request):  
    d = {"username":'jason','password':123,'hobby':['read',{'username':['jason','egon']}]}
    ")
    return render(request,'index.html',locals())  
<p>{{ d.hobby.1.username.1 }}</p>

句可以通过多个句点符的方式去获取需要的数据

二.模版语法之过滤器

  • |length:获取长度
  • |add:加法运算
  • |default:判断是否为空
  • |truncatechars:截取字符(指定数量字符中会包括三个点)
  • |truncatewords:截取单词(截取指定单词数目,会额外添加三个点)
  • |filesizeformat:自动计算文件大小(MB,GB等)
  • |slice:切片
  • |date:日期格式化
  • |safe:转义

过滤器语法:过滤器 |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数

from django.shortcuts import render
from datetime import datetime
# 该模块可以帮助后端直接转义前端标签
from django.utils.safestring import mark_safe
# Create your views here.

def index(request):
    # python所有的数据类型都支持传递给html页面
    i = 11
    f = 11.11
    s = 'hello world'
    str = 'hello world'
    list = [1, 2, 3, 4, 5, 6]
    d = {"username": 'jason', 'password': 123, 'hobby': ['read', {'username': ['jason', 'egon']}]}
    t = (1, 2, 3, 4, 5, 6, 7,)
    se = {1, 2, 3, 4, 5, 6}
    b = True
    ff = False
    ff = False
    ss = 'kjasdklas ksd;lk  akjsdkl da  kjda k;lak d k;a dk  ska d'
    sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡'
    file_size = 32213213424
    ddd = datetime.now()
    #可以传入前端转义
    res = "<h1>你好啊</h1>"
    # 直接传是不会被前端识别并展示到浏览器中的
    res1 = "<script>alert(123)</script>"
    #可以直接在后端就进行转义
    res2 = mark_safe("<h1>你好啊</h1>")
    return render(request, 'index.html', locals())

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ s|length }}</p>
<p>{{ i|add:10 }}</p>  <!--加法运算必须前后都是数字或者字符串-->
<p>{{ b|default:'判断是否为空,得到的是布尔值' }}</p> <!--若有值返回True,没有值返回|右面的参数-->
<p>{{ s|truncatechars:8 }}</p>
<p>{{ ss|truncatewords:3 }}</p>
<p>{{ file_size|filesizeformat }}</p>
<p>{{ s|slice:'0:3:2' }}</p>
<p>{{ ddd|date:'Y年/m月/d日' }}</p> <!--注意time模块时间戳不可以转换-->
<p>{{ res1 }}</p>  <!--后端标签语言传入前端是失效的,防止一些恶意脚本攻击-->
<p>{{ res|safe }}</p><!--可以通过safe转义-->
<p>{{ res2 }}</p><!--也可以在前端通过from django.utils.safestring import mark_safe中的mark_safe方法-->

</body>
</html>

前后端取消转义
	前端
		|safe
	后端
		from django.utils.safestring import mark_safe
		mark_safe('<h1>安全滴</h1>')
总结:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用
这样的话 你就可以利用到后端更加多的逻辑语法

三.模版语法之标签

  • 前端for循环中forloop参数
{% for foo in list %}
    <p>{{ forloop }}</p>
{% endfor %}

得到下图,可以看到有first,last等方法

  • 前端if条件
{% for foo in list %}
    {% if forloop.first %}
        <p>这是第一个值</p>
    {% elif forloop.last %}
        <p>这是第一个值</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
{% endfor %}

补充:for循环的对象必须是可迭代对象或者不为空,否则无法执行,可以通过empty方法

a = []
{% for foo in a %}
    {% if forloop.first %}
        <p>这是第一个值</p>
    {% elif forloop.last %}
        <p>这是第一个值</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for循环的对象内没有值</p>
{% endfor %}

keys,vlues,items同样可以使用

d = {"username": 'jason', 'password': 123, 'hobby': ['read', {'username': ['jason', 'egon']}]}
{% for foo in d.items %}
    <p>键值对:{{ foo }}</p>
{% endfor %}

{% for foo in d.keys %}
    <p>key:{{ foo }}</p>
{% endfor %}

{% for foo in d.values %}
    <p>值:{{ foo }}</p>
{% endfor %}

补充:可以通过with起别名快速获取值

<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码</p>
<p>{{ d.hobby.1.username.1 }}</p>

<!--或者通过with起一个别名,就可以快速调用-->

{% with d.hobby.1.username.1 as ag %}
    <p>{{ ag }}</p>
{% endwith %}

四.自定义过滤器,标签,inclusion_tag

  • 前戏准备工作
1.在应用名下新建一个名字必须叫templatetags文件夹
	2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
	3.在该文件内 必须先写以下两句代码
		from django.template import Library		
		register = Library()
# 自定义过滤器的创建和使用

1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个名称为mytag.py的文件
mytag.py

from django.template import Library		
register = Library()

# 自定义过滤器,给过滤器起个名字my_sum
@register.filter(name='my_sum')

def index(a, b):
    # 注意此处省略了逻辑校验
    return a + b


index.html文件中使用过滤器

<p>自定义过滤器的使用</p>
{#先将自定义的过滤器加载过来#}
    
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>

注意:过滤器最多只能传两个参数,即|左右(如果非要传多个参数,可以通过x|name:[1,2,3,4]等方式手动处理)

# 自定义标签的创建和使用

1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个名称为mytag.py的文件
mytag.py

from django.template import Library		
register = Library()

# 自定义标签
@register.simple_tag(name='my_simpletag')
def newtag(a, b, c, d):
    return '%s?%s?%s?%s'%(a, b, c, d)


index.html文件中使用过滤器

<p>自定义标签的使用</p>
{% load mytag %}
<p>{% my_simpletag 1 2 3 4 %}</p>


# 这里可以得出:标签是{%  %},并且可以传多个参数,过滤器是{{}},只能传两个参数,并且通过simple_tag创建的标签不能作为条件使用for循环和if逻辑语句,而通过filter创建的过滤器就可以使用if逻辑语句


# 自定义inclusion_tag的创建和使用

#inclusion_tag的作用:
#    比如在一个html页面上调用一个inclusion_tag,这个inclusion_tag会调用一个函数并生成一些数据,这些数据会放到一个html页面上进行渲染,将渲染好的页面再传回inclusion_tag的位置(类似于函数的装饰器,可以额外添加到某个已经写好的html页面


# 第一步:自定义inclusion_tag
@register.inclusion_tag('demo.html',name='my_name')
def index1(n):
    list1 = []
    for i in range(n):
        list1.append(i)
    # 将列表数据传递给demo.html
    # 注意用locals传的时候是传全部变量
    return locals()
    #或者使用字典的形式是指定参数传值
    # return {'list':list}

# 第二步,可以新建一个demo.html文件接收数据(只需要部分能实现功能的代码就好)
<div>
    {% for foo in list1 %}
        <li>{{ foo }}</li>
    {% endfor %}

</div>


# 第三步:调用inclusion_tag
<p>自定义inclusion_tag的使用</p>
{% load mytag %}
{% my_name 10 %}


五.模版的继承和导入

  • 继承
模板的继承
	某一个页面大部分区域都是公用的 那这个页面就可以作为模板页面
	当别人继承这个页面之后 如何修改对应的区域
	
	先在模板页面上通过block实现划定区域
		{% block content %}	
			模板页面内容
		{% endblock %}
	
	子页面中先导入整个模板
		{% extends '模板页面.html'%}
		修改特定的区域  通过实现划定好的区域名称
		{% block content %}
			子页面内容
		{% endblock %}
	
	通常情况下 模板页面页面应该起码有三块区域
		{% block css %}	
			模板页面内容
		{% endblock %}
		{% block content %}	
			模板页面内容
		{% endblock %}
		{% block js %}	
			模板页面内容
		{% endblock %}
	# 模板的block块越多 可扩展性越高
	
	还支持子页面调用父页面对应区域的内容 并且可以无限次调用
		{{ block.super }}
  • 导入
模板的导入
	将html页面当做模块使用 哪里需要导哪里  这个html页面通常都不是完整的 只是一个局部样式
	{% include 'left.html' %}
posted @ 2020-01-08 00:47  Mr江  阅读(125)  评论(0编辑  收藏  举报