日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

フィルタを自作する

Djangoのフィルタを自作するときには、Djangoのお作法に従ってファイルを配置します。
まずアプリケーションディレクトリの下に、"templatetags"というディレクトリを作成します。このディレクトリ名は決め打ちです。また、パッケージとして扱うのでディレクトリの下に __init__.py を置くことを忘れずに。
次に、sample_filters.py ファイルを作成して下記のサンプルのように編集します。

# vim:fileencoding=utf-8
from django import template
from django.template.defaultfilters import stringfilter

import urllib

register = template.Library()

@register.filter(name='urlencode2')
@stringfilter
def urlencode2(value, encoding):
    return urllib.quote_plus(value.encode(encoding))

@で始まる行は、Pythonのデコレータです。ここで指定しているのは、urlencode2という関数を urlencode2という名前のフィルターとして登録していること。それと、このフィルターは文字列だけを処理するように指定していることです。文字列なので、数値型や日付型にフィルタ指定をしても無視されます。

次に、first.html を編集して、urlcondeとの挙動の違いを確認します。

<html>
<head>
</head>
<body>
{% load sample_filters %}

<p>サンプルアプリケーション はじめの一歩</p>

<p>{{ none_data|default:"Noneは置き換えられます" }}</p>

<p>{{ empty_data|default:"空文字列も置き換えます" }}</p>

<p>{{ none_data|default_if_none:"Noneは置き換えられます" }}</p>

<p>{{ empty_data|default_if_none:"空文字列は置き換えられません。" }}</p>

<p>system default: {{ abc|urlencode }}</p>

<p>utf-8: {{ abc|urlencode2:"utf-8" }}</p>

<p>sjis: {{ abc|urlencode2:"sjis" }}</p>

</body>
</html>

まず、load で .py の名前を指定します。その後、フィルタの使い方としては、ビルトインフィルタと同じ使い方になります。
urlencode2では引数として、URLエンコードするときに文字列の文字コードを指定しています。これをブラウザで表示すると次のようになると思います。

<html>
<head>
</head>
<body>


<p>サンプルアプリケーション はじめの一歩</p>

<p>Noneは置き換えられます</p>

<p>空文字列も置き換えます</p>

<p>Noneは置き換えられます</p>

<p></p>

<p>system default: abc%E3%81%A7%E3%81%99%E3%81%A8%EF%BC%81</p>

<p>utf-8: abc%E3%81%A7%E3%81%99%E3%81%A8%EF%BC%81</p>

<p>sjis: abc%82%C5%82%B7%82%C6%81I</p>

</body>
</html>

実際にHTMLをレンダリングしてみるとわかるのですが、標準の urlencode フィルタは UTF-8で文字列を扱ってURLエンコードをしているのがわかると思います。
自前のシステム内で閉じているときには意識する必要がありませんが、外部のサービスなどと連携したリンクを生成しなければいけない時に、このやり方は非常に役に立つと思います。

次回は、カスタムタグを作ってみたいと思います。