一、模板语法
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 %}
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"> # 第二种方式