Django基础(6)_自定义标签过滤器扩展
在Django基础(5)中我们已经介绍了Django模板自带的一些常用过滤器(filter)。今天就讲下Django模板过滤器(filter)的本质及工作原理, 并详细讲解如何自定义模板过滤器。
模板过滤器(filter)的作用
Django模板中的变量是用双括号如{{ variable }}显示的。通过使用模板过滤器(filter)来可以改变变量在模板中的显示形式,比如{{ article.title | lower }} 中lower过滤器可以让文章的标题转化为小写。Django的模板提供了许多内置过滤器,一些常用的过滤器如下。
过滤器 | 例子 |
lower | {{ article.title | lower }} 大小写 |
length | {{ name | length }} 长度 |
default | {{ value | default: "0" }} 默认值 |
date | {{ pub_date | date:"Y-m-d" }} 日期格式 |
过滤器(filter)的本质和工作原理
Django模板过滤器(filter)的本质是一个函数,过滤器的名字就是函数名。该函数接收竖线" | "前的变量值(value)和冒号" : " 后的参数(args),返回一个值, 其中args可选。比如lower过滤器接收一个字符串,将其全部转化为小写后返回。date过滤器调用strftime方法将DateTime格式的数据转化为指定格式的字符串返回。
我们自定义过滤器本质就是自定义一个名叫my_filter_name(value, args)的函数,用来处理模板中传递过来的变量和参数。在使用自定义过滤器时时我们需要遵循先载入再使用的原则。
我们先在源码中直接添加一个过滤器
随便点击一个过滤器函数就可以进入defaultfilters.py源码文件中了
下面就来测试一下我们添加的过滤器
咳咳, 以上作为了解即可
首先你要在你的app目录下新建一个叫templatetags的文件夹(不能取其它名字), 里面必需包含__init__.py的空文件。在该目录下你还要新建一个python文件专门存放你自定义的过滤器函数,本例中为blog_extras.py,当然你也可以取其它名字。整个目录结构如下所示:
1 blog/ 2 __init__.py 3 models.py 4 templatetags/ 5 __init__.py 6 blog_extras.py 7 views.py
在模板中使用自定义的过滤器(filter)时,需要先使用{% load blog_extras %}载入自定义的过滤器,然后通过使用{{ variable | my_filter_name }} 使用。
案例1 - 自定义过滤器显示中文格式日期
Django自带的过滤器date:"Y-m-d" 可以将日期类型的数据转化为”2018-09-01“。如果使用date:"Y年-m月-d日", 则日期将显示为"2018年-09年-01日", 这显然不是我们想要的。我们现在希望自定义一个名叫chinese_date_format的过滤器,在模板中使用{{ pub_date | chinese_date_format }}即可将博文发布日期转化为“2018年9月1日”显示。
此时我们只需要在blog_extras.py文件中添入如下代码。
from django import template register = template.Library() @register.filter() def chinese_date_format(value): return "{}年{}月{}日".format(value.year, value.month, value.day)
我们从先建立模板的register,然后使用@register.filter过滤器注册我们自定义的过滤器chinese_date_format。在模板中先使用{% load blog_extras %}载入自定义的过滤器,然后在模板中使用{{ article.pub_date | chinese_date_format }} 即可显示中文格式日期了。
但上述代码有个问题,该过滤器只有当value为datetime格式的数据时才会工作。如果用户把它用在一个字符串上则会出现AttributeError。
我们现在可以对上述代码进行改进,先增加对value格式的判断。当value格式不为datetime时,该过滤器直接返回value本身。
1 from django import template 2 import datetime 3 register = template.Library() 4 5 6 @register.filter 7 def chinese_date_format(value): 8 if isinstance(value, datetime.datetime): 9 return "{}年{}月{}日".format(value.year, value.month, value.day) 10 else: 11 return value
views.py中:
1 from django.shortcuts import render 2 import datetime 3 def time(request): 4 time = datetime.datetime.now() 5 return render(request, 'time_t.html', {"time": time})
time.html
<body> {% load mytags %} {{ time|chinese_date_format }} </body>
看效果吧:
案例2 - 自定义过滤器给标题添加"最新"和"推荐"描述
案例1中我们只使用了竖线"|"前的变量值作为参数,我们还可以通过冒号:给过滤器函数传递更多的参数。我们现在要自定义一个叫add_description的过滤器。当我们在模板中使用{{ article.title | add_description:"最新" }}时,标题后面会加上"最新"字样。当我们在模板中使用{{ article.title | add_description:"最热" }}时,标题后面会加上"最热"字样。
blog_extras.py中代码如下所示。
1 from django import template 2 register = template.Library() 3 4 5 @register.filter 6 def add_description(value, args): 7 return "{} ({})".format(value, args)
模板标签都是放在{% %}括号里的,常见的模板标签有{% load xxxx %}, {% block xxxx %}, {% if xxx %}, {% url 'xxxx' %}。这些模板标签的本质也是函数,标签名一般即为函数名。这些标签的主要作用包括载入代码渲染模板或对传递过来的参数进行一定的逻辑判断或计算后返回。
比如下例中的url标签接收两个参数,一是命名的url, 一个是文章id,将其进行反向解析,生成一个类似blog/article/4/的链接。
1 <a href="{% url 'blog:article_detail' article.id %}">详情</a>
Django模板标签(tags)的分类
Django的模板标签(tag)一共分2类:
-
simple_tag (简单标签 : 处理数据,返回一个字符串或者给context设置或添加变量。
-
inclusion_tag (包含标签) : 处理数据,返回一个渲染过的模板。
熟悉Django的都知道,我们一般在视图view里设置context,然后通过它来传递数据给模板。 一个context是一系列变量和它们值的集合。通过使用simple_tag, 我们可以在视图外给context设置或添加变量。注: Django 1.9以后不再支持assignment_tag了,均使用simple_tag。
如何自定义模板标签
首先你要在你的app目录下新建一个叫templatetags的文件夹(不能取其它名字), 里面必需包含__init__.py的空文件。在该目录下你还要新建一个python文件专门存放你自定义的模板标签函数,本例中为blog_extras.py,当然你也可以取其它名字。整个目录结构如下所示:
blog/
__init__.py
models.py
templatetags/
__init__.py
blog_extras.py
views.py
在模板中使用自定义的模板标签时,需要先使用{% load blog_extras %}载入自定义的过滤器,然后通过{% tag_name %} 使用它。
#blog_extra.py
1 from django import template 2 import datetime 3 from blog.models import Article 4 5 register = template.Library() 6 7 # use simple tag to show string 8 @register.simple_tag 9 def total_articles(): 10 return Article.objects.filter(status='p').count() 11 12 # use simple tag to set context variable 13 @register.simple_tag 14 def get_first_article(): 15 return Article.objects.filter(status='p').order_by('-pub_date')[0] 16 17 # show rendered template 18 @register.inclusion_tag('blog/latest_article_list.html') 19 def show_latest_articles(count=5): 20 latest_articles = Article.objects.filter(status='p').order_by('-pub_date')[:count] 21 return {'latest_articles': latest_articles, }
# latest_article_list.html
1 <ul> 2 {% for article in latest_articles %} 3 <li>{{ article.title }} </li> 4 {% endfor %} 5 </ul>
# index.html (使用我们自定义的模板标签)
1 {% extends "blog/base.html" %} 2 {% load blog_extras %} 3 4 {% block content %} 5 6 <p>文章数: {% total_articles %}</p> 7 {% show_latest_articles %} 8 9 {% get_first_article as first_article %} 10 <p>第一篇文章: </p> 11 <p>{{ first_article.title }}</p> 12 13 {% endblock %}
了解更多请点击=>
本文来自博客园,作者:长情不羁的五年,转载请注明原文链接:https://www.cnblogs.com/grlend/articles/14032000.html