# 第五節:自定義過濾器
# 自定義模版過濾器
雖然`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