Django模板系统

官方文档

参考1

参考2

1. 模板系统(字符串替换)
    1. 语法
        1. 变量相关: {{ name }},{{name|length}},{{name|default:"默认值"}}
        2. 逻辑相关:
            1. if判断
                {% if a > b %}
                {% endif %}
                
                {% if a > b %}
                {% else %}
                {% endif %}
                
                {% if a > b %}
                {% elif %}
                {% else %}
                {% endif %}
            2. for循环
                1. for循环的基本用法:
                    {% for i in name_list %}
                        {{ i }}
                    {% endfor %}
                    
                    {% for i in name_list %}
                        {{ i }}
                    {% empty %}
                        空空如也
                    {% endfor %}
                
                2. for循环可用的属性:
                    forloop.counter
                    forloop.counter0
                    forloop.revcounter
                    forloop.revcounter0
                    
                    forloop.first 
                    forloop.last 
                    
                    forloop.parentloop  --> 两层for循环,内层循环引用外层循环
                    
    2. filter
        1. 常用的内置filter
            1. length
            2. filesizeformat       --> 格式化文件大小的
            3. date:'Y-m-d H:i:s'   --> 格式化时间的
            4. slice
            5. safe                 --> XSS攻击(跨站脚本攻击)
            6. truncatechars:20     --> 截取字符,超过的用...表示
            7. default
                
        2. 自定义的filter
            示例:
                1. addsb
                2. addstr
            具体的实现方式:
                1. 定义阶段
                    1. 在app下面新建一个python的包:templatetags
                    2. 在上面的Python包中新建一个Python文件,名字随意
                    3. 在上述python文件中:
                        from django import template
                        
                        # 生成一个注册用的实例
                        register = template.Library()
                        # 定义并注册一个自定义的filter函数
                        @register.filter(name='addsb')
                        def add_sb(arg):
                            return "{} sb".format(arg)
                2. 调用阶段:
                    1. 在Django的模板文件中,导入刚才新建的python文件
                        {% load py文件名 %}
                    2. 按照filter的语法调用
                        {{ name|addsb }}
内容概要 
1. 模板语言(字符串替换)
    1. 母版和继承
        1. 什么时候用母版?
            html页面有重复的代码,把它们提取出来放到一个单独的html文件。
            (比如:导航条和左侧菜单)
        2. 子页面如何使用母版?
            {% extends 'base.html' %}   --> 必须要放在子页面的第一行
            
            母版里面定义block(块),子页面使用block(块)去替换母版中同名的块
    2. 组件
        1. 什么时候用组件?
            重复的代码,包装成一个独立的小html文件。
        2. 如何使用?
            {% include 'nav.html' %}
            
    3. Django模板语言中关于静态文件路径的灵活写法
        1. 利用Django模板语言内置的static方法帮我拼接静态文件的路径
            {% load static %}
            <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
        2. 利用内置的get_static_prefix获取静态文件路径的别名,我们自行拼接路径
            {% load static %}
            <link href="{% get_static_prefix %}bootstrap/css/bootstrap.min.css" rel=stylesheet>
        3. as语法(一个路径多次用到,可以使用as保存到一个变量,后面就直接使用变量代替具体路径)
    4. 自定义的simple_tag
        比filter高级一点点
        它可以接受的参数个数大于2
    
    5. 自定义的inclusion_tag
        用来返回一段html代码(示例:返回ul标签)
        
        1. 定义阶段
            在app下面新建templatetags 文件夹(注意是Python包)
            新建一个py文件
            
            from django import template
            # 生成注册示例,名字必须是register
            register = template.Library()
            @register.inclusion_tag("ul.html")
            def show_ul(num):
                num = 1 if num < 1 else int(num)
                data = ["第{:0>3}号技师".format(i) for i in range(1, num+1)]
                return {"data": data}

        2. 调用阶段
            {% load xx %}
            {% show_ul 10 %}
内容概要1 

一、语言变量相关语法

只需要记两种特殊符号:

{{  }}和 {% %}

变量相关的用{{}},逻辑相关的用{%%}。

         

2、字典测试:

 

 

3、模板语言类与列表测试:

# 测试用类
class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        return '{} 今天好开心,跑了三米'.format(self)

    def __str__(self):
        return '<Person-object {}>'.format(self.name)

# 模板语言测试相关
def template_test(request):
    p1 = Person('小白', 9000)
    p2 = Person('小黑', 10000)
    p_list = [p1,p2]
    return render(
        request,
        "t_text.html",
        {
           "person1":p1,
            "person2":p2,
            "p_list":p_list
        })

  

 二、模板语言之filter 

 在Django的模板语言中,通过使用 过滤器 来改变变量的显示。

过滤器的语法: {{ value|filter_name:参数 }}

使用管道符"|"来应用过滤器。

例如:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。

注意事项:

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

 Django的模板语言中提供了大约六十个内置过滤器。

1、default

如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。

{{ value|default:"nothing"}}

如果value没有传值或者值为空的话就显示nothing

2、length

返回值的长度,作用于字符串和列表。

{{ value|length }}

返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

3、filesizeformat

将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

4、slice

切片:切字符串和列表,不能切数字

{{value|slice:"2:-1"}}

5、date

格式化

{{ value|date:"Y-m-d H:i:s"}}
from datetime import datetime
now = datetime.now()
<p>时间格式化:{{ now|date:"Y-m-d H:i:s" }}</p>

 

6、safe

Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

比如:

value = "<a href='#'>点我</a>"

{{ value|safe}}

例:

 a_html = "<a href='http://www.sogo.com'>我是后端传过来的a标签</a>"

7、truncatechars 

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:截断的字符数

{{ value|truncatechars:9}}

8、truncatewords

在一定数量的字后截断字符串。

{{ value|truncatewords:9}}

例:

    p_str = """
        在苍茫的大海上,狂风卷积着乌云,在乌云和大海之间,海燕像黑色的闪电,在高傲地飞翔。
    """

 

9、cut

移除value中所有的与给出的变量相同的字符串

{{ value|cut:' ' }}

如果value为'i love you',那么将输出'iloveyou'.

10、join

使用字符串连接列表,例如Python的str.join(list)

11、timesince

将日期格式设为自该日期起的时间(例如,“4天,6小时”)。

采用一个可选参数,它是一个包含用作比较点的日期的变量(不带参数,比较点为现在)。 例如,如果blog_date是表示2006年6月1日午夜的日期实例,并且comment_date是2006年6月1日08:00的日期实例,则以下将返回“8小时”:

{{ blog_date|timesince:comment_date }}

分钟是所使用的最小单位,对于相对于比较点的未来的任何日期,将返回“0分钟”。

12、timeuntil

似于timesince,除了它测量从现在开始直到给定日期或日期时间的时间。 例如,如果今天是2006年6月1日,而conference_date是保留2006年6月29日的日期实例,则{{ conference_date | timeuntil }}将返回“4周”。

使用可选参数,它是一个包含用作比较点的日期(而不是现在)的变量。 如果from_date包含2006年6月22日,则以下内容将返回“1周”:

{{ conference_date|timeuntil:from_date }}

13、自定义filter

自定义过滤器只是带有一个或两个参数的Python函数:

  • 变量(输入)的值 - -不一定是一个字符串
  • 参数的值 - 这可以有一个默认值,或完全省略

例如,在过滤器{{var | foo:'bar'}}中,过滤器foo将传递变量var和参数“bar”

步骤:

1、自定义filter代码文件摆放位置:

1. 在app下面新建一个package package包:templatetags

2. 在上面的Python包中新建一个Python文件,名字随意

 

 2、在myfilter.py文件中编写自定义filter  

from django import template
# 生成一个注册用的实例
register = template.Library()

# 定义并注册一个自定义的filter函数
# 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫nihao
@register.filter(name="nihao")
def add_nihao(arg):
    return "{} nihao.".format(arg)

# 告诉Django的模板语言我现在有一个自定义的filter方法,名字叫addstr
@register.filter(name="addstr")
def add_str(arg, arg2):
    """
    第一个参数永远是管道符前面那个变量
    :param arg: 道符前面那个变量
    :param arg2: 冒号后面的变量
    :return:
    """
    return "{} {}.".format(arg, arg2) 

3、使用自定义filter

 'name': '王镇',

 

{# 先导入我们自定义filter那个文件 #}
{% load myfilter %}
{# 使用我们自定义的filter #}
{{ name|nihao }}
{# 打印结果:王镇 nihao #}
{{ name|addstr:"跑得快~" }}
 {# 打印结果:王镇 跑得快~  #}
{{ name|addstr:"跳的高~" }}
{# 打印结果:王镇 跳的高~ #} 

三、Tags 

1、注释 

{# ... #} 

2、for循环

(1)普通for循环:

<ul>
    {% for name in name_list %}
        <li>{{ name }}</li>
    {% endfor %}
</ul>

for循环可用的一些参数:

 示例:

  name_list = ['张三', '李四', '王五']
<ul>
    {% for name in name_list %}
        {% if forloop.last %}
            <li class="dsb">{{ forloop.revcounter }}-{{ name }}</li>
        {% else %}
            <li class="{% if forloop.first %}'sb'{% endif %}">{{ forloop.revcounter }}-{{ name }}</li>
        {% endif %}
    {% endfor %}
</ul>

  

 (2)双层for循环:

name_list2 = [['张三0', '李四0', '王五0'], ['张三1', '李四1', '王五1']]
{% for name in name_list2 %}
    {% for name1 in name %}
        {{ forloop.parentloop.counter }}
        {{ forloop.counter }}
        {{ name1 }}
    {% endfor %}
{% endfor %}

 

 (2)for ... empty

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>

如果user_list没有值就执行empty下面的语句

3、if判断

if,elifelse

{% if p3 %}
    <p>p3:{{ p3 }}</p>
{% elif p2 %}
    <p>p2:{{ p2 }}</p>
{% else %}
    <p>什么人都没有!</p>
{% endif %}

上面只有p2,所以执行p2下面的语句

当然也可以只有if和else

{% if name_list|length >= 3 %}
    <p>需要打两辆车</p>
{% else %}
    <p>一辆足矣!</p>

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

4、with

定义一个中间变量,多用于给一个复杂的变量起别名。

注意等号左右不要加空格。

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

{% with business.employees.count as total %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

5、csrf_token

这个标签用于跨站请求伪造保护。

在页面的form表单里面写上{% csrf_token %}

6、注意事项

1. Django的模板语言不支持连续判断(python支持):

  

  

2. Django的模板语言中属性的优先级大于方法

def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})

如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:

{{ data.items }}

默认会取d的items key的值100。

例如:

 

四、母板和继承

1. 为什么要有模板和继承:
把多个页面公用的部分提取出来,放在一个 母版 里面。
其他的页面只需要 继承 母版就可以了。
2. 具体使用的步骤:
1. 把公用的HTML部分提取出来,放到base.html文件中
2. 在base.html中,通过定义block,把每个页面不同的部分区分出来
3. 在具体的页面中,先继承母版
4. 然后block名去指定替换母版中相应的位置

3. 使用母版和继承的注意事项:
1. {% extends 'base.html' %} --> 母版文件:base.html要加引号
2. {% extends 'base.html' %}必须放在子页面的第一行!!!
3. 可以在base.html中定义很多block,通常我们会额外定义page-css和page-js两个块
4. view.py相应的函数中返回的是对应的子页面文件 不是 base.html

1、继承母板

在子页面中在页面最上方使用下面的语法来继承母板。

{% extends 'layouts.html' %}

2、块(block)

通过在母板中使用{% block  xxx %}来定义"块"。

在子页面中通过定义母板中的block名来对应替换母板中相应的内容。

{% block page-main %}
  <p>世情薄</p>
  <p>人情恶</p>
  <p>雨送黄昏花易落</p>
{% endblock %}

3、组件

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

{% include 'navbar.html' %}
<!DOCTYPE html>
<!-- saved from url=(0042)https://v3.bootcss.com/examples/dashboard/ -->
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="https://v3.bootcss.com/favicon.ico">

    <title>图书管理系统</title>
    <!-- Bootstrap core CSS -->
    <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="/static/dashboard.css" rel="stylesheet">
    <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css">

    {% block page-css %}

    {% endblock %}
</head>

<body>

{% include 'navbar.html' %}

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
            <ul class="nav nav-sidebar">
                <li class="{% block publisher_class %}{% endblock %}"><a href="/publisher_list/">出版社列表页</a></li>
                <li class="{% block book_class %}{% endblock %}"><a href="/book_list/">书籍列表</a></li>
                <li class="{% block author_class %}{% endblock %}"><a href="/author_list/">作者列表</a></li>
            </ul>

        </div>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            {# 这里是每个页面不同的部分 #}
            {% block page-main %}

            {% endblock %}
        </div>
    </div>
</div>
</div>


<div class="modal fade" tabindex="-1" role="dialog" id="myModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title">用户信息</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal">
                    <div class="form-group">
                        <label for="inputEmail3" class="col-sm-2 control-label">邮箱</label>
                        <div class="col-sm-10">
                            <input type="email" class="form-control" id="inputEmail3" placeholder="Email">
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="inputPassword3" class="col-sm-2 control-label">密码</label>
                        <div class="col-sm-10">
                            <input type="password" class="form-control" id="inputPassword3" placeholder="Password">
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                <button type="button" class="btn btn-primary">保存</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
{% block page-js %}

{% endblock %}
</body>
</html>
base.html

五、静态文件相关

1、{% static %}

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

引用JS文件时使用:

{% load static %}
<script src="{% static "mytest.js" %}"></script>

某个文件多处被用到可以存为一个变量

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

2、{% get_static_prefix %}(了解)

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

六、simple_tag

和自定义filter类似,只不过接收更灵活的参数。

定义注册simple_tag

@register.simple_tag(name="plus")
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)

使用自定义simple_tag

{% load mysimpletag %}

{# simple_tag #}
{% plus "1" "2" "abc" %}

七、inclusion_tag

多用于返回html代码片段

示例:

templatetags/my_inclusion.py

from django import template

register = template.Library()

@register.inclusion_tag('result.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}项".format(i) for i in range(1, n+1)]
    return {"data": data}
<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>
result.html
from django import template

register = template.Library()

@register.simple_tag(name="yimi")
def my_sum(arg1, arg2, arg3):
    return "{} {} {}".format(arg1, arg2, arg3)

@register.inclusion_tag('results.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}项".format(i) for i in range(1, n+1)]
    return {"results": data}
mysimpletag.py

 

posted @ 2020-04-24 16:01  zh_小猿  阅读(114)  评论(0编辑  收藏  举报