1. 程式人生 > >Django自定義過濾器

Django自定義過濾器

為什麼要自定義過濾器?

Django中雖然已經內建了很多過濾器,但是並不能滿足我們的日常開發,所以我們需要自定義過濾器。

首先我們先搭建好一個測試環境。
在一個新建的專案中建立一個article的app,然後在article中新建一個urls.py的檔案,然後在templates中新建一個index.html的檔案,(如果沒有templates這個資料夾需要手動建立),然後進行配置,使article中的views對index.html進行渲染。直至配置好測試環境。

在一切配置好了之後,然後在article中新建一個名為templatetagspackage
注意: 必須是一個包,並且包的名字也必須為templatetags


package和資料夾的區別package中會有一個__init__.py的檔案。只用擁有__init__.pypackage才能被匯入。
建包方法:article資料夾上右鍵=>new=>Python Package.然後名字為templatetags

然後在templatetags中新建一個python檔案,檔名就可以隨便取了,我這裡就新建了一個my_filter.py的檔案。
在裡面寫入我們自定義的過濾器的規則:

from django import template

register = template.Library()

#過濾器函式主體,第一個引數是過濾器前面的值, 第二個引數是過濾器後面的值
#可以不用有第二個引數,但是必須要有第一個引數,引數最多兩個 def greet(value,word): return value + word #註冊自定義的過濾器 # 過濾器的名字 過濾器的主體函式 register.filter('greet',greet)

這裡我麼就自定義好了一個過濾器,它的功能是將字元竄進行拼接。
然後在views中寫入程式碼

from django.shortcuts import render

# Create your views here.
def index(request):
    context = {
'value':'張三'} return render(request,'index.html',context=context)

然後配置url,然後在index.html編寫程式碼:
首先,要想我們自定義的過濾器被執行,我們必須先將包含過濾器的app進行註冊。即將這裡的article新增到settings.INSTALLED_APS中,不然Django也找不到這個過濾器。
其次,在渲染的html檔案中的程式碼最上面載入自定義的過濾器:

{% load my_filter %}

這裡的my_filter是我定義過濾器的檔名。
這樣,在html中才能使用我們自定義的過濾器。
然後在index.html中的body中寫入程式碼:

{{ value|greet:'world' }}

接下來就自行輸入網址,和改變引數進行測試。
這樣,我們的過濾器就從定義到使用的完全弄好了。

總結(建立過濾器的基本步驟):

  1. 首先在某個app中,建立一個python包,叫做templatetags,注意,這個包的名字必須為templatetags,不然就找不到。
  2. 在這個templatetags包下面,建立一個python檔案用來儲存過濾器。
  3. 在新建的python檔案中,定義過濾器(也就是函式),這個函式的第一個引數永遠是被過濾的那個值,並且如果在使用過濾器的時候傳遞引數,那麼還可以定義另外一個引數。但是過濾器最多隻能有2個引數。
  4. 在寫完過濾器(函式)後,要使用django.template.Library.filter進行註冊。
  5. 還要把這個過濾器所在的這個app新增到settings.INSTALLED_APS中,不然Django也找不到這個過濾器。
  6. 在模板中使用load標籤載入過濾器所在的python包。
  7. 然後就是使用自定義的過濾器了。
  8. django.template.Library.filter還可以當作裝飾器來使用。如果filter函式沒有傳遞任何引數,那麼將會使用這個函式的名字來作為過濾器的名字。當然如果你不想使用函式的名字來作為過濾器的名字,也可以傳遞一個name引數。

實戰案例 :自定義時間計算過濾器

有時候經常在朋友圈,微博中可以看到一條資訊發表的時間,並不是具體的時間,而是距離現在多久,比如:剛剛1分鐘前等,DTL內建的過濾器是沒有這個功能的。因此我們需要自定義一個這樣的過濾器。

首先我們先開啟my_filter.py這個檔案。
修改程式碼為:

from django import template

register = template.Library()

#過濾器函式主體,第一個引數是過濾器前面的值, 第二個引數是過濾器後面的值
#可以不用有第二個引數,但是必須要有第一個引數,引數最多兩個
@register.filter('greet')  #和下面的register.filter('greet',greet)功能是一樣的
#1.可以不用傳引數,即預設使用下面的函式名作為過濾器的名字
#2.也可以傳入一個引數,即自定義過濾器的名字。
#3.最多隻能傳一個引數。
def greet(value,word):
    return value + word

#註冊自定義的過濾器
#            過濾器的名字 過濾器的主體函式
register.filter('greet',greet)

然後我們使用了另外一種方法來註冊我們的過濾器。這樣我們就可以把下面的register.filter('greet',greet)刪掉了也能實現效果。

接下來我們在my_filter.py中自定義我們的時間過濾器

from django import template
from datetime import datetime

register = template.Library()

@register.filter
def time_since(value):
    '''
    time距離現在時間的間隔
    1.如果時間間隔小於一分鐘以前,那麼就顯示剛剛。
    2.如果是大於一分鐘小於一小時,那麼就顯示xx分鐘前
    3.如果是大於一小時小於24小時,那麼就是顯示xx小時以前
    4.如果是大於24 小時小於30天以內,那麼就顯示xx天以前
    5.否則就顯示具體的時間 2017-10-04 12:45
    '''
    if not isinstance(value,datetime):
        return value
    now = datetime.now()
    #time.total_seconds()將時間轉化為秒數
    timestamp = (now - value).total_seconds()
    if timestamp < 60:
        return '剛剛'
    elif timestamp > 60 and timestamp < 60*60:
        minutes = int(timestamp/60)
        return '%s分鐘前' % minutes
    elif timestamp > 60*60 and timestamp < 60*60*24:
        hours = int(timestamp/60/60)
        return '%s小時前' % hours
    elif timestamp > 60*60*24 and timestamp < 60*60*24*30:
        days = int(timestamp/60/60/24)
        return '%s天前' % days
    else:
        return value.strftime("%Y-%m-%d %e:%M")

在views中傳遞一個引數:

from django.shortcuts import render
from datetime import datetime

# Create your views here.
def index(request):
    context = {'value':'張三','time':datetime(year=2018,month=8,day=20,hour=19,minute=8,second=0)}
    return render(request,'index.html',context=context)

然後在index.html中使用time_since過濾器
首先在檔案最上面新增一行程式碼載入我們的過濾器。

{% load my_filter %}

然後在body中寫入

{{ time|time_since }}

然後就可以檢視效果了,如果需要改變時間,只需要去views中修改time的值就行了。

==注意:==如果測試不成功,請仔細按照上面的總結來檢查哪一步出錯了。