Django框架之【自定义模板过滤器与标签】
扫码关注我的公众号 大佬打赏渠道
1.自定义模板过滤器与标签的需求
Django框架模板的过滤器与标签就是在Django框架的模板文件中实现某种功能。Django框架自带有许多的模板过滤与标签,但有时候还需要自定义模板过滤器与标签。
以将数据库中存储的人员数据中性别这一项的数据传递显示到应用前端为例,在数据库中,为了节省存储空间,类似于只有 男
和 女
这种二值项数据,一般都用0和1存储。但这也为后端与前台的数据交互提出一个问题:前端向后端提出查看性别数据的请求,后端直接返回的是0和1的数据,并不符合人们的直接阅读习惯。而自定义模板过滤器就可以解决这个问题,它可以将传递过来的0和1对应的转化为人们更乐于接受的 男
和 女
这种显示的表示。当然,你也可以在后端将从数据库中读取出来的数据全部转化为对应的显示表示后再传递给模板文件,但是这样你的代码往往不够简练、清晰。
至于自定义标签,也可以解决类似上面的问题。但自定义模板标签更加强大,它可以干任何事情。
2.自定义模板过滤器与标签的代码布局
首要的问题是,自定义模板过滤器与标签在哪里定义?要将代码写在什么地方?
代码布局的要点
-
代码写在app目录下的名为
tempaltetags
的文件夹【必须叫这个名字】。这个文件夹必须是一个python的包,这个文件夹下一定要有__init__.py
的文件,最好直接创建pythonpackage
,将其命名为tempaltetags
,这样会自动包含__init__.py
文件。 -
自定义的模板标签或模板过滤器就放在这个包下的python模块中(python脚本文件)
-
app必须在
settings.py
中被注册
settings.py
文件中在【 INSTALLED_APPS
】配置中加上app应用名 teacher
-
INSTALLED_APPS =[
-
'django.contrib.admin',
-
'django.contrib.auth',
-
'django.contrib.contenttypes',
-
'django.contrib.sessions',
-
'django.contrib.messages',
-
'django.contrib.staticfiles',
-
# 实际中只在调试的时候用到staticfiles,实际布署的时候用的ngix
-
'teacher'
-
]
2.自定义模板过滤器
定义
-
自定义过滤器就是一个python函数,它有一个或2个参数
-
第一参数就是那个传进来的模板变量【任意数据类型】
-
第二个参数是一个普通参数,可以是默认参数,也可以不要这个参数
例子:这里的自定义过滤器是将数据库中的性别 sex
项中存储的值0和1转换为对应的女和男。
自定义过滤器的功能是: 接受0和1,分别转换成女和男
视图函数中数据库的模拟
sex为1代表男性,sex为0代表女性
-
def student_list_view(request):
-
students =[
-
{'id':1,'name':'小明','age':18,'sex':1},
-
{'id':3,'name':'小花','age':17,'sex':0},
-
{'id':19,'name':'小李','age':18,'sex':1},
-
{'id':100,'name':'小红','age':18,'sex':0},
-
]
-
return render(request,'teacher/students_list.html',context={'students':students})
这里一共提供三种转换方法:if条件选择写法、三目运算符写法和字典键值对转换。
其实,if条件选择写法和三目运算符写法并没有本质区别,python中也没用像java或其他编程语言中有三目运算的专门写法,只不过将多行代码写到了一行中,使得你的程序更加 pythonic
!
以下便是三种方法的具体代码与注释:
-
# 转换性别的过滤器
-
# 接受0和1,分别转换成女和男
-
def my_sex(value):
-
"""
-
转换性别的过滤器
-
:param value:
-
:return :
-
"""
-
# if条件选择写法
-
if value =='1':
-
return'男'
-
else:
-
return'女'
-
-
# 三目运算符写法
-
return'男'if value else'女'
-
-
# 字典键值对转换
-
map ={
-
0:'女',
-
1:'男'
-
}
-
return map[value]
注册
自定义模板过滤器的注册有两种方法,一般用装饰器注册。
但是无论哪种方法,首先都要实例化一个 Library()
对象。值得注意的是,接受实例化对象的变量名必须为register,不能有任何改变。
-
from django.template importLibrary
-
# 实例化
-
register =Library()# 必须用register这个变量名
普通的注册方法
-
'''
-
注册方法一:普通注册方法
-
'''
-
-
# 自定义filter
-
def my_sex(value):
-
"""
-
转换性别的过滤器
-
:param value:
-
:return :
-
"""
-
# if条件选择写法
-
map ={
-
0:'女',
-
1:'男'
-
}
-
return map[value]
-
-
# 注册,并命名为xxx,
-
# 注意:命名后,自定义filter应用的时候用xxx
-
register.filter('xxx',my_sex)
利用装饰器注册的方法
-
'''
-
注册方法二:装饰器注册方法
-
'''
-
# 注册,并命名为xxx
-
# 注意:命名后,自定义filter应用的时候用xxx
-
@register.filter(name='xxx')
-
def my_sex(value):
-
"""
-
转换性别的过滤器
-
:param value:
-
:return :
-
"""
-
# if条件选择写法
-
map ={
-
0:'女',
-
1:'男'
-
}
-
return map[value]
在模板中使用自定义过滤器
首先,load过滤器所在的py文件名,引入自定义的过滤器模块,也就是 templatetags
包里的那个python文件。【注意:新建了 templatetags
包,要重启一下Django服务】接下来,你就可以在模板文件中使用你的自定义过滤器了,自定义过滤器的用法与内置的过滤器用法完全一样,这里就不再赘述了。
在模板文件中加载自定义过滤器
-
{% extends 'teacher/base.html'%}
-
# 在模板文件中加载自定义过滤器
-
{% load teacher_filter %}
-
{% block title %}学生列表{% endblock %}
向自定义过滤器传递2个参数
这里有一个新的需求,如果我们的网页是面向世界的,需要支持多种语言,简单起见,譬如说就支持中文和英文。这时候如何实现语言的切换。具体应用场景还是以上面的例子来说。
首先,定义好一个能接受两个参数的自定义过滤器。
默认语言参数language为中文 'ch'
-
def my_sex(value,laguage='ch'):
-
"""
-
转换性别的过滤器
-
:param value:
-
:return :
-
"""
-
# if条件选择写法
-
map ={
-
'zh':{0:'女',1:'男'},
-
'en':{0:'female',1:'male'}
-
}
-
return map[laguage][value]
其次,在自定义过滤器应用文件中加载自定义过滤器并应用。
-
{% extends 'teacher/base.html'%}
-
{% load teacher_filter %}
-
{% block title %}学生列表{% endblock %}
-
-
...
-
-
<td>{{ student.sex|my_sex:'en'}}</td>
-
-
...
最终效果
3.自定义模板标签
模板标签可以干任何事情
标签类型
(1).简单标签
简单标签与过滤器没有太大的区别
简单标签的注册: django.template.Library.simple_tag()
注册方法与自定义过滤器一样。
简单标签可以接受许多参数,处理后返回信息。
创建、注册一个简单标签的实例代码
-
from django.template importLibrary
-
from datetime import datetime
-
-
register =Library()
-
-
def current_time(format_str='%Y-%m-%d %H:%M:%S'):
-
"""
-
就输出当前时间
-
:param format_str:
-
:return:
-
"""
-
return datetime.now().strftime(format_str)
-
-
# 注册,并命名为current
-
register.simple_tag(current_time,name='current')
模板中的使用
-
{%extends'teacher/base.html'%}
-
{% load teacher_tags %}
-
....
-
<p>
-
当前时间:{% current format_str='%Y-%m-%d'}
-
</p>
-
-
# 跟普通函数的传参一样,字符串、模板变量、关键字参数都可以传递
-
# 也可以直接写{% current '%Y-%m-%d' %}
-
{% current format_str='%Y-%m-%d'%}
使用上下文变量
在自定义标签中,使用当前调用标签的视图函数中的上下文变量
使用当前模板中的上下文变量context
创建、注册
-
from django.template importLibrary
-
from datetime import datetime
-
-
register =Library()
-
-
# 自定义简单标签的函数中也要传递context
-
def current_time(context,format_str='%Y-%m-%d %H:%M:%S'):
-
"""
-
就输出当前时间
-
:param format_str:
-
:return:
-
"""
-
return datetime.now().strftime(format_str),[x for x in context['students']if x['sex']==1]
-
-
# 注意,在注册的时候要加上 takes_context=True
-
register.simple_tag(current_time,name='current',takes_context=True)
应用
-
{% extends 'teacher/base.html'%}
-
{% load teacher_filter %}
-
{% load teacher_tags %}
-
{% block title %}学生列表{% endblock %}
-
{% block content %}
-
<h1>学生列表</h1>
-
<p>当前时间和男性学生分别为:{% current format_str='%Y-%m-%d'%}</p>
-
<table class="table">
效果
(2).包含标签(嵌套标签)
通过渲染另外一个模板展示数据
创建、注册一个包含标签
-
from django.template importLibrary
-
from datetime import datetime
-
from django.template.loader import get_template
-
-
register =Library()
-
-
# 利用装饰器注册自定义包含标签,等同于下面的那种注册方式
-
@register.inclusion_tag('teacher/show_list.html')
-
def show_list(list_data):
-
# 一个嵌套标签,实现展示列表数据
-
return{'ls':list_data}
-
-
# 普通方式注册自定义包含标签,等同于上面的装饰器注册方法
-
# t = get_template('teacher/show_list.html')
-
# register.inclusion_tag(t)(show_list)
包含标签包含的模板文件
这个模板文件存放路径【 templates/teacher/show_list.html
】
-
<ul>
-
{%for l in ls %}
-
<li>{{ l }}</li>
-
{% endfor %}
-
</ul>
显示模板中的应用
-
{%extends'teacher/base.html'%}
-
{% load teacher_filter %}
-
{% load teacher_tags %}
-
...
-
<td>
-
<!-自定义包含标签的应用->
-
{% show_list student.hobby %}
-
</td>
-
...
包含标签的数据流传递路径:
包含标签的作用:
包含标签通过渲染另外一个模板来展示数据,其主要作用便是为了省工省力,有时候一个页面中,我们需要在多处使用类似的复杂操作,这个时候可以通过包含标签来定义其行为,在原来的位置使用包含标签即可,同样的操作使用包含标签只需要写一次代码便可实现多次功能。