模板层

06 模板层

一. 模版语法

{{}}: 变量相关 {%%}: 逻辑相关

1. 注释是代码的规范

{# ... #}

2. 基本数据类型传值

int1 = 123
float1 = 11.11
str1 = '我也想奔现'
bool1 = True
list1 = ['小红', '姗姗', '花花', '茹茹']
tuple1 = (111, 222, 333, 444)
dict1 = {'username': 'jason', 'age': 18, 'info': '这个人有点意思'}
set1 = {'晶晶', '洋洋', '嘤嘤'}

# 基本数据类型都支持
{{ int1 }}
{{ float1 }}
{{ str1 }}
{{ bool1 }}
{{ list1 }}
{{ tuple1 }}
{{ dict1 }}
{{ set1 }}

3. 函数和类传值

def func():
    print('我被执行了')
    return '你的另一半在等你'

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

    @staticmethod
    def get_func():
        return 'func'

    @classmethod
    def get_class(cls):
        return 'cls'
    
    # 对象被展示到html页面上 就类似于执行了打印操作也会触发__str__方法
    def __str__(self):
        return  'cls'

obj = MyClass()


# 传递函数名会自动加括号调用 但是模版语法不支持给函数传额外的参数
{{ func }}

# 传类名的时候也会自动加括号调用(实例化)
{{ MyClass }}

# 内部能够自动判断出当前的变量名是否可以加括号调用 如果可以就会自动执行  针对的是函数名和类名
{{ obj }}
{{ obj.get_self }}
{{ obj.get_func }}
{{ obj.get_class }}


# 总结
'''
1. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
2. 如果使用的变量不存在, 它被默认设置为'' (空字符串) 。
'''

4. 模版语法的取值

django模版语法的取值 是固定的格式 只能采用“句点符”.

{{ dict1.username }}
{{ list1.0 }}</p>
{{ dict1.hobby3.info }}

5. 模板语法的优先级

.在模板语言中有特殊的含义。当模版系统遇到点.,它将以这样的顺序查询:

'''
1. 字典查询(Dictionary lookup)
2. 属性或方法查询(Attribute or method lookup)
3. 数字索引查询(Numeric index lookup)
'''

二. Filters过滤器(注意: 过滤器只能最多有两个参数)

过滤器就类似于是模版语法内置的 内置方法.

django内置有60多个过滤器我们这里了解一部分即可

过滤器语法: {{数据|过滤器:可选参数}}

注意事项:

1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
2. 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
4. '|'左右没有空格没有空格没有空格

Django的模板语言中提供了大约六十个内置过滤器我们这里介绍14种:

# 统计长度: 作用于字符串和列表。
    {{ str1|length }}
    
    
# 默认值: 第一个参数布尔值是True就展示第一个参数的值否则就展示冒号后面的值
    {{ bool1|default:'谁的布尔值为True谁就展示' }}
    
    
# 文件大小:
    {{ file_size|filesizeformat }}  # 9.8 KB 
    
    
# 日期格式化:  将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等
    {{ current_time|date }}         # May 29, 2020
    {{ current_time|date:'Y-m-d' }}      # 2020-05-29
    {{ current_time|date:'Y-m-d H:i:s' }}    # 2020-05-29 01:31:09
    
    
# 切片操作: 支持步长
    {{ list1|slice:'0:4:2' }}
    
    
# 切取字符: 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾 (注意: 包含这三个点)
    {{ info|truncatechars:9 }}   
    
    
# 切取单词: 不包含三个点 按照空格切取, 不是识别单词语法
    {{ msg|truncatewords:3 }}    
    
    
# 移除特定的字符:
    {{ msg|cut:' '}}    
    

# 拼接操作: 
    # join
        {{ info|join:'$' }}
    # 加法: 数字就相加  字符就拼接
        {{ int1|add:float1 }}
        {{ str1|add:str1 }} 
    
    
# 转义!!!!:
    # 后端的转义
    from django.utils.safestring import mark_safe
    html_safe = mark_safe('<h1>哈哈哈</h1>')

    {{ html }}           # 普通的标签使用模板, 任然是模板
    {{ html_safe }}      # 后端的转义传值
    {{ html|safe }}      # 前端的转义    

date参数介绍:

格式化字符 描述 示例输出
a 'a.m.''p.m.'(请注意,这与PHP的输出略有不同,因为这包括符合Associated Press风格的期间) 'a.m.'
A 'AM''PM' 'AM'
b 月,文字,3个字母,小写。 'jan'
B 未实现。
c ISO 8601格式。 (注意:与其他格式化程序不同,例如“Z”,“O”或“r”,如果值为naive datetime,则“c”格式化程序不会添加时区偏移量(请参阅datetime.tzinfo) 。 2008-01-02T10:30:00.000123+02:002008-01-02T10:30:00.000123如果datetime是天真的
d 月的日子,带前导零的2位数字。 '01''31'
D 一周中的文字,3个字母。 “星期五”
e 时区名称 可能是任何格式,或者可能返回一个空字符串,具体取决于datetime。 '''GMT''-500''US/Eastern'
E 月份,特定地区的替代表示通常用于长日期表示。 'listopada'(对于波兰语区域,而不是'Listopad'
f 时间,在12小时的小时和分钟内,如果它们为零,则分钟停留。 专有扩展。 '1''1:30'
F 月,文,长。 '一月'
g 小时,12小时格式,无前导零。 '1''12'
G 小时,24小时格式,无前导零。 '0''23'
h 小时,12小时格式。 '01''12'
H 小时,24小时格式。 '00''23'
i 分钟。 '00''59'
I 夏令时间,无论是否生效。 '1''0'
j 没有前导零的月份的日子。 '1''31'
l 星期几,文字长。 '星期五'
L 布尔值是否是一个闰年。 TrueFalse
m 月,2位数字带前导零。 '01''12'
M 月,文字,3个字母。 “扬”
n 月无前导零。 '1''12'
N 美联社风格的月份缩写。 专有扩展。 'Jan.''Feb.''March''May'
o ISO-8601周编号,对应于使用闰年的ISO-8601周数(W)。 对于更常见的年份格式,请参见Y。 '1999年'
O 与格林威治时间的差异在几小时内。 '+0200'
P 时间为12小时,分钟和'a.m。'/'p.m。',如果为零,分钟停留,特殊情况下的字符串“午夜”和“中午”。 专有扩展。 '1 am''1:30 pm' / t3>,'midnight','noon','12:30 pm' / T10>
r RFC 5322格式化日期。 'Thu, 21 Dec 2000 16:01:07 +0200'
s 秒,带前导零的2位数字。 '00''59'
S 一个月的英文序数后缀,2个字符。 'st''nd''rd''th'
t 给定月份的天数。 28 to 31
T 本机的时区。 'EST''MDT'
u 微秒。 000000 to 999999
U 自Unix Epoch以来的二分之一(1970年1月1日00:00:00 UTC)。
w 星期几,数字无前导零。 '0'(星期日)至'6'(星期六)
W ISO-8601周数,周数从星期一开始。 153
y 年份,2位数字。 '99'
Y 年,4位数。 '1999年'
z 一年中的日子 0365
Z 时区偏移量,单位为秒。 UTC以西时区的偏移量总是为负数,对于UTC以东时,它们总是为正。 -4320043200

三. 标签

1. for循环

forloop.first 第一次循环返回True, 其余返回False
forloop.last 最后一次循环返回False, 其余返回True
forloop.counter 当前循环次数. 从1开始
forloop.counter0 当前循环索引. 从0开始
forloop.revcounter 当前循环次数取反
forloop.revcounter0 当前循环索引取反
forloop.parentloop 本层循环的外层循环

展示格式:

{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
{'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
{% for foo in list1 %}
    <p>{{ forloop }}</p>
    <p>{{ foo }}</p>  # 一个个元素
{% endfor %}

2. if判断

# if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断
{% if bool1 %}
    <p>1111</p>
{% elif int1 %}
    <p>2222</p>
{% else %}
    <p>3333</p>
{% endif %}

3. for与if混合使用

Copy{% for foo in list1 %}
    {% if forloop.first %}
        <p>这是我的第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次啊</p>
    {% else %}
        <p>上面都不是才轮到我</p>
    {% endif %}

    {% empty %}
        <p>for循环的可迭代对象内部没有元素 根本没法循环</p>
{% endfor %}

4. 处理字典values,keys,items方法

{% for foo in dict1.values %}
    <p>{{foo}}</p>
{% endfor %}

{% for foo in dict1.keys %}
    <p>{{foo}}</p>
{% endfor %}

{% for foo in dict1.items %}
    <p>{{foo}}</p>
{% endfor %}

5. with起别名

在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式

dict1 = {'username': 'egon', 'hobby': ['吃', '喝', '玩', {'info': '他喜欢吃生蚝!!!'}]}

# 书写方式一: as语句
{% with dict1.hobby.3.info as nb %}
    <p>{{ nb }}</p>
    {# 与上面等同, 但是长语句, 还是使用with赋值来进行 #}
    <p>{{ dict1.hobby.3.info }}</p>
{% endwith %}


# 书写方式二: 赋值
{% with nb=dict1.hobby.3.info %}
    <p>{{ nb }}</p>
    {# 与上面等同, 但是长语句, 还是使用with赋值来进行 #}
    <p>{{ dict1.hobby.3.info }}</p>
{% endwith %}

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

1. 准备步骤

1. 在应用下创建一个名字”必须“叫templatetags文件夹
2. 在该文件夹内创建“任意”名称的py文件
3. 在该py文件内"必须"先书写下面两句话(单词一个都不能错)
    from django import template
    register = template.Library()

2. 自定义过滤器

强调: 自定义过滤器函数, 最大只能设有2个形参

from .templatetags.mytag import register
@register.filter(name='my_sum')
def abc(v1, v2):  # abc函数名任意. 导入自定义过滤器使用的是上面指定的name的值
    return v1 + v2


# 使用: (注意: 先导入我们自定义filter那个文件mytag)
{% load mytag %}
<p>{{ int1|my_sum:100 }}</p>

3. 自定义标签

# 自定义标签: 数可以有多个 类似于自定义函数
from .templatetags.mytag import register
@register.simple_tag(name='my_join')
def abc(a, b, c, d):  # abc函数名任意. 导入自定义标签使用的是上面指定的name的值
    return f'{a}-{b}-{c}-{d}'

# 使用: 标签多个参数彼此之间空格隔开(注意: 先导入我们自定义filter那个文件mytag)
{% load mytag %}
p>{% my_join 'json' 123 123 123 %}</p>

4. 自定义inclusion_tag

img

'''
内部原理:
    先定义一个方法 
    在页面上调用该方法 并且可以传值
    该方法会生成一些数据然后传递给一个html页面
    之后将渲染好的结果放到调用的位置
'''
from .templatetags.mytag import register
@register.inclusion_tag('left_memu.html')  # 注意: 这里传的是渲染的HTML文件, 不需要指定关键字name
def left(n):
    data = ['第{}项'.format(i) for i in range(n)]
    # 第一种: 将data传递给left_menu.html
    # return {'data':data}

    # 第二种: 将data传递给left_menu.html
    return locals()


# left_memu.html
{% for foo in data %}
    {% if forloop.first %}
        <p>{{foo}}</p>
    {% elif forloop.last %}
        <p>{{ foo }}</p>
    {% endif %}
{% endfor %}


# index使用(注意: 先导入我们自定义filter那个文件mytag)
{% load mytag %}
{% left 5 %}

五. 模板的继承

# 模版的继承 你自己先选好一个你要想继承的模版页面
{% extends 'home.html' %}


# 继承了之后子页面跟模版页面长的是一模一样的 你需要在模版页面上提前划定可以被修改的区域
{% block content %}
	模版内容
{% endblock %}


# 子页面就可以声明想要修改哪块划定了的区域
{% block content %}
	子页面内容
{% endblock %}


# 一般情况下模版页面上应该至少有三块可以被修改的区域, 这样每一个子页面就都可以有自己独有的css代码 html代码 js代码
{% block css %}
    1.css区域
{% endblock %}

{% block content %}
    2.html区域
{% endblock %}

{% block js %}
    3.js区域
{% endblock %}


"""
一般情况下 模版的页面上划定的区域越多 那么该模版的扩展性就越高
但是如果太多 那还不如自己直接写
"""

六. 模版的导入

"""
将页面的某一个局部当成模块的形式
哪个地方需要就可以直接导入使用即可
"""
'''静态导入'''
{% include 'wasai.html' %}


'''动态导入'''
# 被导入的text.html
<p>{{ name }}</p>   {# 这里的name就是"egon"#}

# 导入html的文件
{% include 'text.html' with name='"egon"' %}
    
    
# 不过上面的导入的参数是写死的. 如果你想动态的通过模板语法传参, 你可以这样
{% include 'text.html' with name=username %}    {#注意哦! 这里的username是视图层传过来的哦!#}
# 被导入文件中如果想{{ name }}模板以后是字符串的格式你可以这也指定即可!
<p>'{{ name }}'</p>   {#注意: 如果不加引号, 这种字符串的格式的话, 那么name模板传值以后就是一个变量.#}

七. 总结

# 模板语法的母亲 -> 注释
    {# #}

# 模板语法2种书写语法
    # 变量相关: {{}}
    # 逻辑相关: {%%}

# 支持的数据类型:
    # 基本数据类型: int float bool str tuple list set dict
    # 函数和类: function, class
        注意:
        1. 默认调用拿到的是返回值.
        2. 无法传值. 如果需要传值的类型, 那么这个模板语法就不会生效.
        3. 类中定义__str__方法, {{obj}}会触发其执行.

# 模板语法的取值:
    固定格式. 句点符. 支持连点, 支持索引, 支持键.
    例子: {{ user.name.0.1.0.info }}


# 过滤器: 最多只能有2个参数
    # 语法: {{ 数据|过滤器:可选参数 }}
    # 过滤器介绍:
        |length               获取长度
        |default:默认值        指定默认值. 前面布尔值为False才展示后面指定的参数 内部使用return v1 or v2
        |filesizeformat       返回人性化文件大小格式KB MB....
        |date:'Y-m-d'         返回 年-月-日 时间格式
        |slice:'0:4:2'        切片 支持步长
        |truncatechars:9      截取字符 包含三点
        |truncatewords:9      截取单词 不包含三点 以空格区分
        |cut:' '              移除特定字符
        |join:'$'             拼接操作
        |add:99               数字就加  字符就拼接
        |safe                 前端 取消转义
        from django.util.safestring import mark_safe
        res = mark_safe('<h1>我是你爸爸</h1>')
        {{ res }}             后端 取消转义

# 标签
    # for循环
        {% for i in user_list %}
            {{ forloop }}
            forloop.first         循环到第一次  True
            forloop.last          循环到最后一次 False
            forloop.counter       当前循环次数
            forloop.counter0      当前循环索引
            forloop.revcounter    当前循环次数取反
            forloop.revcounter0   当前循环索引取反
        {% endfor %}

    # if判断
        {% if 条件 %}
            ...
        {% elif %}
            ...
        {% else %}
            ...
        {% endif %}

    # for与if混合使用
        {% for i in user_list %}
            {% if forloop.first %}
                ...
            {% if forloop.last %}
                ...
            {% endfor %}
            {% empty %}
                迭代对象为空时触发
        {% endfor %}

    # 处理字典的values, keys, items方法
    # with取别名
        {% with user.name.0.1.0.info as xxx %}
        {% with xxx=user.name.0.1.0.info %}
            {{ xxx }}
        {% endwith  %}


# 自定义过滤器
    # 三步骤:
        1. 先在需要使用过滤器的应用中创建templatetags文件夹
        2. 接着进入文件夹中创建任意名称的.py文件. -->  mytag.py
        3. 写入以下固定格式的内容:
            from django import template
            register = template.Library()

    # 自定义过滤器: 最多2个参数
        # 视图层定义
            from templatetags.mytag import register
             @register.filter(name='过滤器名称 -> my_sum')
             def 任意函数名(v1, v2):
                return v1 + v2
        # 模板层使用
            {% load mytag %}
            {{ v1|my_sum:v2 }}

    # 自定义标签: 任意参数
        # 视图层定义
            from templatetags.mytag import register
            @register.simple_tag(name='标签名称 -> my_join')
            def 任意函数名(a, b, c, d):
                return f'{a}-{b}-{c}-{d}'

        # 模板层使用
            {% load mytag %}
            {{ my_join 111 222 333 444 }}

    # 自定义inclusion_tag
        # 视图层定义
           from templatetags.mytag import register
            @register.inclusion_tag('需要传递数据的html文件 -> index.py')
            def left(n):
                data = [f'第{i}项' for i in range(n)]
                return locals()          # 传递数据方式1
                # return {"data": data}  # 传递数据方式2

        # index.py定义
            <ul>
            {% for item in data %}
                <li>{{ item }}</li>
            {% endfor %}
            </ul>

        # 模板层使用
            {% load mytag %}
            {% left 5 %}

# 模板的继承
    # 子页面声明需要继承的模板页面
        {% extends '模板页面名' %}

    # 需要被划分模板页面中的某块区域
        {% block context %}
            ...
        {% endblock %}

    # 子页面声明替换区域
        {% block context %}
            ...
        {% endblock %}

    # 一般一情况下子页面有3种独立的形式. 提示: 太多不如不继承
        js, css, html

# 模板的导入
    {% include '.html' %}
posted @ 2020-10-19 13:46  为了等  阅读(99)  评论(0编辑  收藏  举报