Django之深刻了解模板层

模板语法

前端模板的语法只记住两种就好了。html

{{ xxx }} 变量相关的
{ %  % } 逻辑相关的

模板传值

咱们经过后端,能够传给前端的数据,数据类型哪些可以接收,哪些不能接收?前端

前端基本上能接受全部后端全部的数据类型。python

只要是后端可以加括号调用的,传递到html页面上都会自动加括号调用,可是若是是 函数有形参就不能调用了,html页面也不能传参。django

views.py:
def test(request):
    a = 1
    b = 1.11
    c = 'str'
    d = [11,22]
    e = (11,22)
    s = {11,22}
    f = {"user":'age'}
    g = True

    def test1():
        return 'ok'

    class test2(object):
        def get_self(self):
            return 'get_self'

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

        @staticmethod
        def get_func():
            return 'get_func'
    obj = test2()

    # 咱们以前是经过这种方式来给前端传值的,若是须要传的值很是的多的话,这样写就比较麻烦,
    # return render(request,'test.html',{"a":a})
    # 能够经过locals()这种方式,将当前全部的名称空间中的名字都传给前端。
    return render(request,'test.html',locals())


test.html:
<body>
# 接收普通变量
<h1>{{ a }}</h1>
<h1>{{ b }}</h1>
<h1>{{ c }}</h1>
<h1>{{ d }}</h1>
<h1>{{ e }}</h1>
<h1>{{ f }}</h1>
<h1>{{ g }}</h1>
<h1>{{ s }}</h1>    

# 接收函数
<h1>{{ test1 }}</h1>    

# 接收类
<h1>{{ test2 }}</h1>

# 接收对象
<h1>{{ obj }}</h1>

# 对象.方法调用
<h1>{{ obj.get_self }}</h1>
<h1>{{ obj.get_cls }}</h1>
<h1>{{ obj.get_func }}</h1>
</body>

# 打印结果:
1
1.11
str
[11, 22]
(11, 22)
{'user': 'age'}
True
{11, 22}
ok
<app01.views.test.<locals>.test2 object at 0x000000000BAD11D0>
<app01.views.test.<locals>.test2 object at 0x000000000BA9ADD8>
get_self
get_cls
get_func

过滤器

什么是过滤器?后端

模板语法中,提供给你了一些内置的方法,帮你快速的处理后端传过来的数据。这个是模板语法的过滤器。app

过滤器 语法结构:xx|xxxx:变量 | 操做函数

常见的一些过滤器:oop

过滤器 描述
length 统计长度
add: 加法运算
slice:'' 切片操做
default: 判断是否有值,若是没有值使用默认值
filesizeformat 自动计算文件大小
truncatechars: 截取几个字符,算上...(三个点)
truncatewords: 按照空格截取几个单词,不算...(三个点)
safe 前端展现带有标签的文本

有一种后端在传递前端数据的时候,若是后端发送了一个数据是带有html标签的,是不会自动转换的,那么咱们既可使用上面自带的过滤器转义,也能够后端转移事后在发过来。code

前端转义:

from django.utils.safestring import mark_safe
sss = '<h2>我是带有标签的字符串</h2>'
sss = mark_safe(sss)
return render(request,'test.html',locals())
views.py:

def test(request):
    a = 1
    b = 1.11
    c = 'stdsdsddsdsr'
    d = [11,22]
    e = (11,22)
    s = {11,22}
    f = {"user":'age'}
    g = True
    is_value = ''
    filesize = 3212144324
    _str = 'dahsdk dsadbukab daku dasn dbda dan dwa wa dwad wawd w'
    sss = '<h2>我是带有标签的字符串</h2>'
    sss = mark_safe(sss)
    return render(request,'test.html',locals())

test.html:

<h1>
模板语法中的过滤器会自动将|左边的数据当作右边过滤器的第一个参数传进去
过滤器其实就是个函数 def length(value):
</h1>
<h1>统计c的长度:{{ c|length }}</h1> # 其实源码中就是 len(value)
<h1>加法运算:{{ a|add:10 }}</h1>
<h1>切片操做,顾头不顾尾:{{ c|slice:'0:2' }}</h1>
<h1>判断变量是否有值(有值展现值自己,没有值展现默认值):{{ is_value|default:'is_value变量名的值为空' }}</h1>
<h1>自动转大小格式:{{ filesize|filesizeformat }}</h1>  # 自动转大小格式:3.0 GB
<h1>截取文本的内容(字符),截取五个字符,三个点也算:{{ c|truncatechars:5 }}</h1>
<h1>截取文本的内容(按照空格计算),截取五个字符,三个点不算:{{ c|truncatewords:5 }}</h1>
<h1>默认状况下,若是后端发送了一个数据是带有html标签的,是不会自动转换的
是由于放置恶意攻击,若是有脚本执行了就完蛋了。</h1>
<h1>展现带有标签的文本:{{ sss }}</h1>

标签

标签是一些逻辑相关的,好比for循环,if判断。

语法结构:{ % % }

伪代码例子

{% for foo in c %}
    {% if forloop.first %}
        <p>这是第一个值 {{ foo }}</p>
    {% elif forloop.last %}
        <p>这是最后一个值 {{ foo }}</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>当for循环的对象时空的时候会走这个</p>
{% endfor %}

若是后端传过来一些比较复杂的数据:

好比:

comp_dic = {'username': 'jason', 'hobby':
        ['read', 'study',
         ['run', 'rap', {'age': 18}]
         ]
                }

我想要提取出年龄:
模板语法只有一种方式取值:统一采用句点符(点点点方式)
<h1>{{ comp_dic.hobby.2.2.age }}</h1>
18

那么当这个数是经过比较复杂的点点点获取到的,
后续又须要常常使用,能够给该数据起一个别名,
别名只能在with内部使用
{% with comp_dic.hobby.2.2.age as age  %}
    <h1>{{ age }}</h1>
{% endwith %}

自定义过滤器和标签

django支持用户自定义本身的过滤器和标签

自定义的必需要有三步准备:

  1. app名下新建一个名字必须交templatetags的文件及
  2. 在该文件夹内新建一个py文件,名字随便起
  3. 在该py文件中必须写下面两句代码
# 必须写
from django.template import Library
register = Library()

# 自定义的过滤器函数
# 起个别名:bady,跟默认的过滤器同样,最多只能接收两个参数
@register.filter(name='bady')
def minus(a,b):
    return a - b

# 自定义标签,能够接收任意多个参数
@register.simple_tag(name='mytag')
def mytag(a,b,c,d):
    return '%s ? %s ? %s ? %s ?' % (a,b,c,d,)

# 自定义inclusion_tag
# inclusion_tag的做用是主页面以必定的语法给一个参数,调用某个函数,这个函数能够经过主页面给的参数作一些逻辑处理获得一些数据,将数据渲染到一个小html模块,而后将渲染后的小html模块返回给主页面渲染在调用的位置。mytag.html就是临时的一个小页面渲染
@register.inclusion_tag('mytag.html',name='myinclusion_tag')
def myinclusion_tag(n):
    l = []
    for i in range(n):
        l.append('第%s项'%i)
    return locals()

mytag.html:
<ul>
{% for foo in l %}
    <li>{{ foo }}</li>
{% endfor %}
</ul>

实现效果:
* 第0项
* 第1项
8 第2项
* 第3项
* 第4项
* 第5项
* 第6项
* 第7项
* 第8项
* 第9项

使用自定义的过滤器

须要先在html页面上加载

<h1>自定义过滤器的使用</h1>
{% load mytag %}
{{ 2|bady:1 }}  1
{{ 10|bady:2 }} 8

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


使用自定义的标签作逻辑判断
{% if 2|bady:2 %}
    <p>{{ 2|bady:2 }}</p>
{% else %}
    <p>0</p>
{% endif %}

不能不能   !!!!使用自定义的标签作逻辑判断
{% if mytag '1' '2' '3' '4' %}
    <p>有值</p>
{% else %}
    <p>无值</p>
{% endif %}


<h1>自定义的inclusion_tag的使用
当你须要使用一些页面组件的时候,而且该页面组件须要参数才可以渲染
能够考虑使用inclusion_tag</h1>
{% load mytag %}
{% myinclusion_tag 10 %}

模板继承

当写好了一个很是漂亮的页面的时候,其余页面也须要使用这个页面,那么能够考虑使用模板的继承。

须要事先在你想要使用的页面上 划定区域 以后在继承的时候 你就可使用你划定的区域。
也就意味着 若是你不划定任何区域 那么你将没法修改页面内容。

{% block content %}
{% endblock %}

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% block content %}
            {% endblock %}
        </div>
    </div>
</div>

html代码区域 能够设置多个block

新建的html文件就能够继承以前的模板了

{% extends 'template.html' %}


{% block content %}
    {{ block.super }}
    <div class="jumbotron">
  <h1>Hello, world!</h1>
  <p>...</p>
  <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}

模板的继承

  1. 先在你想要继承的页面上经过block划定你未来可能要改的区域
  2. 在子页面上先继承extends
  3. 利用block自动提示 选择你想要修改的内容区域

模板导入

将html页面当作模块直接导入使用

{% include 'template.html' %}
相关文章
相关标签/搜索