# 第五节:自定义过滤器
# 自定义模版过滤器
虽然`DTL`给我们内置了许多好用的过滤器。但是有些时候还是不能满足我们的需求。因此`Django`给我们提供了一个接口,可以让我们自定义过滤器,实现自己的需求。
模版过滤器必须要放在`app`中,并且这个`app`必须要在`INSTALLED_APPS`中进行安装。然后再在这个`app`下面创建一个`Python包`叫做`templatetags`。再在这个包下面创建一个`python文件`。比如`app`的名字叫做`book`,那么项目结构如下:
```
<pre class="calibre12">```
- book
- views.py
- urls.py
- models.py
- templatetags
- my_filter.py
```
```
在创建了存储过滤器的文件后,接下来就是在这个文件中写过滤器了。过滤器实际上就是python中的一个函数,只不过是把这个函数注册到模板库中,以后在模板中就可以使用这个函数了。但是这个函数的参数有限制,第一个参数必须是这个过滤器需要处理的值,第二个参数可有可无,如果有,那么就意味着在模板中可以传递参数。**并且过滤器的函数最多只能有两个参数**。在写完过滤器后,再使用`django.template.Library`对象注册进去。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> template
<span class="hljs-title"># 创建模板库对象</span>
register = template.Library()
<span class="hljs-title"># 过滤器函数</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mycut</span><span class="hljs-params">(value,mystr)</span>:</span>
<span class="hljs-keyword">return</span> value.replace(mystr)
<span class="hljs-title"># 将函数注册到模板库中</span>
register.filter(<span class="hljs-string">"mycut"</span>,mycut)
```
```
以后想要在模板中使用这个过滤器,就要在模板中`load`一下这个过滤器所在的模块的名字(也就是这个python文件的名字)。示例代码如下:
```
<pre class="calibre12">```
{% load my_filter %}
```
```
### 自定义时间计算过滤器:
有时候经常会在朋友圈、微博中可以看到一条信息发表的时间,并不是具体的时间,而是距离现在多久。比如`刚刚`,`1分钟前`等。这个功能`DTL`是没有内置这样的过滤器的,因此我们可以自定义一个这样的过滤器。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-title"># time_filter.py文件</span>
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> template
register = template.Library()
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">time_since</span><span class="hljs-params">(value)</span>:</span>
<span class="hljs-string">"""
time距离现在的时间间隔
1. 如果时间间隔小于1分钟以内,那么就显示“刚刚”
2. 如果是大于1分钟小于1小时,那么就显示“xx分钟前”
3. 如果是大于1小时小于24小时,那么就显示“xx小时前”
4. 如果是大于24小时小于30天以内,那么就显示“xx天前”
5. 否则就是显示具体的时间 2017/10/20 16:15
"""</span>
<span class="hljs-keyword">if</span> isinstance(value,datetime):
now = datetime.now()
timestamp = (now - value).total_seconds()
<span class="hljs-keyword">if</span> timestamp < <span class="hljs-params">60</span>:
<span class="hljs-keyword">return</span> <span class="hljs-string">"刚刚"</span>
<span class="hljs-keyword">elif</span> timestamp >= <span class="hljs-params">60</span> <span class="hljs-keyword">and</span> timestamp < <span class="hljs-params">60</span>*<span class="hljs-params">60</span>:
minutes = int(timestamp / <span class="hljs-params">60</span>)
<span class="hljs-keyword">return</span> <span class="hljs-string">"%s分钟前"</span> % minutes
<span class="hljs-keyword">elif</span> timestamp >= <span class="hljs-params">60</span>*<span class="hljs-params">60</span> <span class="hljs-keyword">and</span> timestamp < <span class="hljs-params">60</span>*<span class="hljs-params">60</span>*<span class="hljs-params">24</span>:
hours = int(timestamp / (<span class="hljs-params">60</span>*<span class="hljs-params">60</span>))
<span class="hljs-keyword">return</span> <span class="hljs-string">"%s小时前"</span> % hours
<span class="hljs-keyword">elif</span> timestamp >= <span class="hljs-params">60</span>*<span class="hljs-params">60</span>*<span class="hljs-params">24</span> <span class="hljs-keyword">and</span> timestamp < <span class="hljs-params">60</span>*<span class="hljs-params">60</span>*<span class="hljs-params">24</span>*<span class="hljs-params">30</span>:
days = int(timestamp / (<span class="hljs-params">60</span>*<span class="hljs-params">60</span>*<span class="hljs-params">24</span>))
<span class="hljs-keyword">return</span> <span class="hljs-string">"%s天前"</span> % days
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">return</span> value.strftime(<span class="hljs-string">"%Y/%m/%d %H:%M"</span>)
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">return</span> value
register.filter(<span class="hljs-string">"time_since"</span>,time_since)
```
```
在模版中使用的示例代码如下:
```
<pre class="calibre12">```
{% load time_filter %}
...
{% value|time_since %}
...
```
```
为了更加方便的将函数注册到模版库中当作过滤器。也可以使用装饰器来将一个函数包装成过滤器。示例代码如下:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django <span class="hljs-keyword">import</span> template
register = template.Library()
<span class="hljs-class">@register.filter(name='mycut')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mycut</span><span class="hljs-params">(value,mystr)</span>:</span>
<span class="hljs-keyword">return</span> value.replace(mystr,<span class="hljs-string">""</span>)
```
```
- Introduction
- 第一章:学前准备
- 第一节:虚拟环境
- 第二节:准备工作
- 第三节:Django介绍
- 第四节:URL组成部分
- 第二章:URL与视图
- 第一节:第一个Django项目
- 第二节:视图与URL分发器
- 第三章:模板
- 第一节:模板介绍
- 第二节:模板变量
- 第三节:常用标签
- 第四节:常用过滤器
- 第五节:自定义过滤器
- 第七节:模版结构优化
- 第八节:加载静态文件
- 第四章:数据库
- 第一节:MySQL相关软件
- 第二节:数据库操作
- 第三节:ORM模型
- 第四节:模型常用字段
- 第五节:外键和表关系
- 第六节:增删改查操作
- 第七节:查询操作
- 第八节:QuerySet API
- 第九节:ORM模型迁移
- 第十节:ORM作业
- 第十一节:ORM作业参考答案
- 第十二节:Pycharm连接数据库
- 第五章:视图高级
- 第一节:限制请求method
- 第二节:页面重定向
- 第三节:HttpRequest对象
- 第四节:HttpResponse对象
- 第五节:生成CSV文件
- 第六节:类视图
- 第七节:错误处理
- 第六章:表单
- 第一节:表单概述
- 第二节:用表单验证数据
- 第三节:ModelForm
- 第四节:文件上传
- 第七章:cookie和session
- 第八章:上下文处理器和中间件
- 第一节:上下文处理器
- 第二节:中间件
- 第九章:安全
- 第一节:CSRF攻击
- 第二节:XSS攻击
- 第三节:点击劫持攻击
- 第四节:SQL注入
- 第十章:信号
- 第一节:什么是信号
- 第十一章:验证和授权
- 第一节:概述
- 第二节:用户对象
- 第三节:权限和分组
- 第十二章:Admin系统
- 第十三章:Django的缓存
- 第十四章:memcached
- 第十五章:Redis