django模版层

django模版层功能:接收视图层传过来的数据,渲染到html模版文件。
此外,还支持模版文件的继承和导入,减少模版文件代码的重复书写。

模版语法

模版语法有两个:{{ }}{% %}

# {{ }}	
变量相关; 用在:传值、过滤器、自定义过滤器filter

# {% %}		
逻辑相关; 用在:标签(if判断 for循环)、自定义标签simple_tag、inclusion_tag、模版继承extend和导入include

模版语法传值

传值使用的模板语法是:{{ }}

传值的类型:python基本数据类型、函数、类、对象等

注意点

  • 变量传值时,既支持python基本的数据类型,还支持函数、类和对象。

  • 如果传递的是函数名,则渲染函数的返回值,且此时函数不能有形参(否则,不做任何处理)。

  • 如果传递的是类名,则会直接实例化一个对象,在前端页面打印该对象。

  • 如果传递的是已经实例化后的对象,如果该对象有__call__方法,则优先执行__call__里面的返回值;如果没有该方法,则再直接打印该对象。

  • 打印对象时,如果对象有__str__方法,则返回该方法的返回值。

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

  • 即可以点键也可以点索引,还可以两者混用。

<p>{{ d.username }}</p>			# 字典使用点key方式
<p>{{ l.0 }}</p>			# 列表使用点索引的方式
<p>{{ obj.get_class }}</p>		# 对象点属性或方法的方式

过滤器

过滤器:类似于是模版语法内置的内置方法;

基本语法{{数据|过滤器:参数}},其中参数是可选的(不需要参数的过滤器不是用参数功能)。

注意:过滤器最多接收两个参数:管道符号前一个,管道符后面一个,如:{{ current_time|date:'Y-m-d H:i:s' }}

补充:过滤器safe比较实用,可以起到保护页面的作用,

# 前端
<p>转义:{{ sss|safe }}</p>
# 后端
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新新</h1>')

常用过滤器

<p>统计长度:{{ s|length }}</p>
<p>默认值(第一个参数布尔值是True就展示第一个参数的值否在展示冒号后面的值):{{ b|default:'啥也不是' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p>
<p>切片操作(支持步长,负步长):{{ l|slice:'0:4:2' }}</p>
<p>切取字符(包含三个点):{{ info|truncatechars:9 }}</p>
<p>切取单词(不包含三个点 按照空格切):{{ egl|truncatewords:9 }}</p>
<p>切取单词(不包含三个点 按照空格切):{{ info|truncatewords:9 }}</p>
<p>移除特定的字符:{{ msg|cut:' ' }}</p>
<p>拼接操作:{{ l|join:'$' }}</p>
<p>拼接操作(数字时加法操作):{{ n|add:10 }}</p>
<p>拼接操作(字符串拼接):{{ s|add:msg }}</p>
<p>转义:{{ hhh|safe }}</p>
<p>转义:{{ sss|safe }}</p>
<p>转义:{{ res }}</p>

标签

for循环
{% for item in li %}
    <p>{{ forloop.counter }}, {{item}}</p>		# 循环打印每循环的索引和元素值
{% endfor %}
    
    
# 补充:forloop
parentloop
counter0			# 循环的索引,从0开始
counter				# 循环的索引,从1开始
revcounter			# 倒序索引
revcounter0
first				# 是否是第一次循环,True/False
last				# 是否是最后一次循环,True/False
if判断
# if判断
{% if b %}
    <p>baby</p>
{% elif s%}
    <p>都来把</p>
{% else %}
    <p>老baby</p>
{% endif %}
for循环和if判断混合使用

注意empty表示,for循环的可迭代对象内部没有元素时,执行的分支。

{% for foo in lll %}
    {% if forloop.first %}
        <p>这是我的第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次啊</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for循环的可迭代对象内部没有元素 根本没法循环</p>
{% endfor %}
with
起别名

with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
另一个好处就是:可以起到缓存优化数据库的作用

# with起别名
{% with d.hobby.3.info as nb  %}
    <p>{{ nb }}</p>			# 在with语法内可以直接使用简洁的nb,代替复杂的d.hobby.3.info
{% endwith %}
字典处理方法

keysvaluesitems

{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}
{% for foo in d.values %}
    <p>{{ foo }}</p>
{% endfor %}
{% for foo in d.items %}
    <p>{{ foo }}</p>
{% endfor %}

自定义过滤器&标签&inclusion_tag

创建并使用自定义过滤器(filter)、标签(simple_tag)、inclusion_tag的流程完全一致。

相同的准备工作

  • 在应用下创建一个名字为templatetags的文件夹
  • 在该文件夹内创建任意名字的py文件(如,mytag.py
  • 在该mytag.py文件里面必须首先做如下配置:
from django import template
		
register = template.Library()
自定义和使用过滤器

功能:和内置过滤器一样,接收并处理视图层传过来的数据

注意:自定义过滤器和内置过滤器一样,最多只能接收两个参数;

# 定义,mytag.py

@register.filter(name='baby')		                # 给过滤器起一个名字 'baby'
def my_sum(v1, v2):					# 该过滤器接受两个参数,并返回参数的和
    return v1 + v2


#使用,xxx.html
{% load mytag %}					# 类似先导入 模块名字 即mytag.py文件
<p>{{ n|baby:666 }}</p>				        # 使用该文件内的baby过滤器,两个参数分类在管道符前后
自定义标签simple_tag

功能:和过滤器类似,接收视图层传过来的数据并做进一步处理

注意:自定义的标签可以接收多个参数

# 定义,mytag.py

@register.simple_tag(name='plus')
def index(a,b,c,d):					# 可以接收多个参数
    return '%s-%s-%s-%s'%(a,b,c,d)


#使用,xxx.html
<p>{% plus 'jason' 123 123 123 %}</p>		        # 多个参数用空格隔开
自定义inclusion_tag

功能:将数据和html页面绑在一起,传给模版文件。数据一般是视图层从数据库里面取出的;html页面一般是模版文件的局部页面。

具体实现

  • 先定义一个方法;
  • 该方法会将返回值交给这个局部的html页面,形成一个绑定了数据的html页面;
  • 然后将这个绑定了数据的html页面传递给模版文件。
# 定义,mytag.py

@register.inclusion_tag('left_menu.html')		# 局部left_menu.html页面接收left方法的返回值
def left(n):
    data = ['第{}项'.format(i) for i in range(n)]
    # 第一种
    # return {'data':data}  # 将data传递给left_menu.html
    # 第二种
    return locals()  # 将data传递给left_menu.html

# 使用, xxx.html
{% left 5 %}

# 补充,也可以给这个inclusion_tag通过参数name起别名,否则直接使用函数名

局部left_menu.html页面,仅仅是书写局部的html语句,在这里面接收left方法的返回值,形成了一个绑定数据的html页面。

模版文件中使用标签left的位置处,渲染这个绑定了数据的left_menu.html页面。

<ul>
    {% for foo in data %}
        <li>{{ foo }}</li>
    {% endfor %}
</ul>

模版继承

目的:较少模版文件的重复书写。相同的部分继承使用,不同的部分自定制。让页面的维护更加简单。

具体实现

  • 提前规划好父模版中子模版需要自定制的区域,该操作不影响父模版文件的内容。
{% block content %}			# 设计子定制化区域,起名为'content'
	模版内容
{% endblock %}
  • 在子模版中,继承父模版,此时会子模版会完全继承父模版,两者的页面内容完全一样。
{% extends 'home.html' %}
  • 定制子模版内容,在选定的区域内,定制自己的内容,不影响父模版的。
{% block content %}		       # 自定制名字为'content'的区域
	子页面内容	
{% endblock %}

总结&补充

  • 模版继承。类似对象的属性查找顺序,先使用自己的的,自己没有使用父类的。
  • 一般情况下模版页面上应该至少有三块可以被修改的区域:css\html\js
  • 每一个子页面都有自己独立的css\html\js代码
  • 一般情况下,模版的页面上划定的区域越多,那么该模版的扩展性就越高;但是如果太多,则因为模版结构混乱而造成可读性差,得不偿失。
{% block css %}
	css文件
{% endblock %}
  
    
{% block content %}
	html内容区域
{% endblock %}


{% block js %}
	js内容区域
{% endblock %}

# 补充:使用父页面的部分内容的接触上再新增其他内容,使用super
{% block content %}
	{{ block.super }}
    # 再自定制化新的内容
{% endblock %}

模版导入

功能:将页面的某一个局部当成模块的形式,哪个地方需要就可以直接导入使用即可。

{% include 'side_bar.html' %}
# 模版导入时传递参数使用 include with
posted @ 2020-05-28 16:28  the3times  阅读(139)  评论(0编辑  收藏  举报