Django之模板层

一、模板语法

1、后端向前端传输数据的方式

# 第一种
 return render(request,'index.html',{'n':n})

 # 第二种
 # locals()会将当前所在的名称空间中的变量名字全部传递给前端页面
 return render(request,'index.html',locals())  


模板常用法语:
{{     }}    变量相关
{% %}    逻辑相关

在Django中的模板语言用{{ 变量名 }}来使用变量,而这个变量的来源通常是在视图函数里面产生的,通过render方法返回到前端,前端通过此语法来使用该变量。

 

2、后端的传递的数据类型

#后端的传递的数据类型可以是:int、str、list、dict、tuple、set、function....

#传递的变量命名规则:包括任何字母数字以及下划线 ("_")的组合, 变量名称中不能有空格或标点符号。

#模板语法规定:使用句点符(就是点号:.)来取出变量中的相关数据,比如字典、列表、元祖、属性方法(对象)

#这里还需要强调一点:模板语法是不支持传参的。


举例:
##后端:views.py##
l = [1,2,3,4,5,user_obj]
user_obj = models.Book.object.filter(id=1).first()
d = {'name': 'sgt', 'password': '123'}


前端:使用模板语法,来处理后端传递过来的变量

{# 取l中的第一个参数 #}
{{ l.0 }}
{# 取字典d中相应的值 #}
{{ d.name }}
{{ d.keys }}
{{ d.values }}
{{ d.items }}

{# 取对象的name属性 #}
{{ user_obj.name }}

{# .操作只能调用不带参数的方法 #}
{{ l.5.name }}

{% with l.5.name  as h %}
{{ h }}
{% endwith %}
{# 将 l.5.name找到的数据起名为h,这样就可以通过h这个名字得到 l.5.name的值 #}

 

函数和类:

##函数
后端:
def func():
        return '你调用了我?'

前端:
{{ func }}

显示结果:你调用了我?

在前端调用后端的函数名(当然此函数名肯定在locals()里面)时,会调用该函数(函数名加括号),得到函数调用的返回值,如果无返回值则为None;
#后端传函数名到前端,会自动加括号调用,但是不支持传参;


##类
后端:
    class Demo(object):
        def __init__(self, name):
            self.name = name
            
        def func(self):
            return self.name
        
        @classmethod
        def test(cls):
            return 'cls'
        
        @staticmethod
        def foo(name,age):
            return 'static_foo'
        
    obj = Demo('sgt')

如果类里面加入:
        def __str__(self):
            return 'Sgt帅得一塌糊涂!'

那么{{ obj }}的结果就会变成:Sgt帅得一塌糊涂!(因为__str__会拦截打印动作,在前端{{ obj }}实际上就是类似于打印obj.

 

另外:

1.前端调用后端数据类型(不需要传参)的内置方法

2.模板语法的注释不会展示到前端页面

3.原生的html注释会展示到前端:<!--我是原生的html注释-->

 

二、过滤器

1、过滤器介绍

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

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

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

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

注意事项:
    过滤器支持链式操作,即一个过滤器的输出结果作为另一个过滤器的输入
    过滤器可以接收参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
    过滤器参数包含空格的话,必须用引号包裹起来,比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
    管道符‘|’左右没有空格。一定要注意,没有空格

 

2、使用案例

前端统计字符串的长度:
<p>{{ s|length }}</p>

前端获取数据如果是空就返回default后面默认的参数值:
<p>{{ flag|default:'你这个东西是个空'}}</p>

将数字格式化成表示文件大小的单位:
<p>{{ file_size|filesizeformat }}</p>


<p>{{ ctime }}</p>    {#June 11,2019,10:36 a.m.#}
格式化时间(不要加百分号)
<p>{{ ctime|date:'Y-m-d' }}</p>     {# 2019-06-11 #}

字符串的切片操作:
<p>{{ res|slice:'0:8' }}</p>
<p>{{ res|slice:'0:8:2' }}</p>

截取固定的长度的字符串 三个点也算:
<p>{{ s|truncatechars:10 }}</p>
按照空格截取文本内容:
<p>{{ res|truncatewords:4 }}</p>

字符串和数字不能混用(返回空):
<p>{{ 'haha'|add:'hehe' }}</p> {# hahahehe #}
<p>{{ 249|add:1 }}</p>    {# 250 #}


ht = <h1>我是h1标签</h1>
sr = <script>alter(123)</script>

<p>{{ ht }}</p>    {# <h1>我是h1标签</h1> #} 不识别h1标签
<p>{{ sr }}</p>    {# <script>alter(123)</script> #} 不识别script标签

前端取消转义
<p>{{ ht|safe }}</p>  加 |safe 后能识别标签
<p>{{ sr|safe }}</p>

后端取消转义
from django.utils.safestring import mark_safe
res = mark_safe('<h1>我是h1标签</h1>')

 

三、标签

1、for循环

后端
ll = [1, 2, 3, 4, 5]

前端
{% for foo in ll %}
     <p>{{ foo }}</p>
{% endfor %}

结果显示:
1
2
3
4
5

 

2、forloop

后端
ll = [1, 2, 3, 4, 5]

前端
{% for foo in ll %}
     <p>{{ forloop }}</p>
{% endfor %}

image

forloop值为下方的字典 :

{'revcounter':反向序号, 'last'(是否是最后一位,True或者False), 'revcounter0':反向索引, 'counter0':(索引), 'parentloop':引用的父级循环对象没有为{}, 
'first': (是否是最后一位,True或者False), 'counter':(序号,从1开始)}

 

3、if判断

{% for foo in l %}
if else
    {% if flag %}
        <p>flag不为空</p>
        {% else %}
        <p>flag是空</p>
    {% endif %}
    
{#(l = ['a', 'b', 'c', 'd', 'e'])#}
{% for foo in l %}
    {% if forloop.first %}
        <p>这是我的第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次了啊</p>
    {% else %}
        <p>嗨起来!!!</p>
    {% endif %}
    {% empty %}   <!--如果l = [],上面的for循环不会进行,只会走这一步-->
        <p>你给我的容器类型是个空啊,没法for循环</p>
{% endfor %}


结果:
l = ['a', 'b', 'c', 'd', 'e']
这是我的第一次
嗨起来!!!
嗨起来!!!
嗨起来!!!
这是最后一次了啊

l = []
你给我的容器类型是个空啊,没法for循环

 

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

1、必须做的三件事

1.在应用名下新建一个名为templatetags文件夹(必须叫这个名字)

2.在该新建的文件夹内新建一个任意名称的py文件

3.在该py文件中需要固定写下面两句代码

 

2、在app01项目程序文件夹新建templatetags文件夹,在此文件夹内新建一个mine.py文件,打开mine.py文件>>输入:

from django import template
register = template.Library()

# 自定义过滤器
@register.filter(name='my_filter')
def index(a, b):
    return a*b

# 自定义标签:
@register.simple_tag
def plus(a, b, c):
    return a+b+c

 

前端html文件内使用过滤器或者标签:

{% load mine %}   <!-- 要使用自定义过滤器和标签,需要先加载自己定义的文件 -->
{{ 9|my_filter:11 }}  <!-- 使用自定义过滤器,注意这里需要用name的值作为使用方法 -->
{% my_tag 1 2 3 %}  <!-- 使用自定义标签,注意这里需要用name的值作为使用方法 -->

结果:
99 
6

 

3、自定义inclusion_tag

inclusion_tag的作用:创建一个动态的html页面文件a.html,这个页面文件a可以在另外一个页面b中被调用,实现这个页面a应该有的功能。
主要作用:通过渲染一个模板来显示一些数据。

# mine.py文件  创建inclusion_tag
from app01 import models 
from django import template
register = template.Library()

@register.inclusion_tag('inclusion_t_test.html', name='my_inclusion')
def func():
    book_list = models.Book.objects.all()
    return {'list': book_list} 


#将book_list的QuerySet对象列表传进inclusion_t_test.html文件
<!-- inclusion_t_test.html文件,被导入的html文件-->
<table>
    <thead>
        <tr>
            <th>id</th>
            <th>title</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
        {% for obj in list %}
            <tr>
                <td>{{ obj.id }}</td>
                <td>{{ obj.title }}</td>
                <td>{{ obj.price }}</td>
            </tr>
        {% endfor %}
    </tbody>
</table>


调用的html页面文件:
{% load mine %}    <!-- 必须要先加载创建标签的文件-->
{% my_inclusion %}  <!-- 调用inclusion_t_test.html页面文件,这里使用该标签的name来调用-->

 

五、模板的继承与模板的导入

1、模板的继承

模板的继承:我们需要使用一个网页中一些固定不变的部分,在不用自己写或者复制的前提下,只需要写几段代码就能拿来在一个新的网页使用,就像一个模板,模板
中变化的地方我们自己指定,其他地方不变,值只变化我们指定的地方。


{% block 给区域起的名字 %}
    前端代码
    ...
{% endblock %}


<!--通常情况下一个模板中应该至少有三块-->
{% block css %}
  页面css代码块
{% endblock %}

{% block js %}
  页面js代码块
{% endblock %}

{% block content %}
  页面主体内容
{% endblock %}

 

模板继承:

{#先继承模板所有的内容#}
        {% extends 'home.html' %}

{#然后根据block块的名字修改指定区域的内容#}
        {% block content %}
            <h1>登录页面</h1>
                <form action="">
                    <p>username:<input type="text" class="form-control"></p>
                    <p>password:<input type="text" class="form-control"></p>
                    <input type="submit" class="btn btn-success">
                </form>
        {% endblock %}


如果在一个block模板中需要保留原始的内容则可以在这个block中任意你想要的位置添加一个{{ block.super }},就可以保留原内容;

 

模板导入:

将一段html当做模块的方式导入到另一个html展示:
{% include '想导入的html文件名' %}

模板导入与自定义inclusion_tag的区别:模板导入的页面内容是静态的、不变的,而通过自定义inclusion_tag导入的页面文件可以是动态的,可动性自己掌控。

 

六、静态文件配置

{% load static %}  
    
    <link rel='stylesheet' href="{% static 'css/mycss.css'%}">  # 第一种方式
    <link rel='stylesheet' href="{% get_static_prefix %}css/mycss.css">  # 第二种方式
posted @ 2019-11-07 14:59  米兰的小铁將  阅读(158)  评论(0编辑  收藏  举报