気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM等について、学んだことや備忘録をアウトプットとして残し、情報を必要としている誰かにとって「かゆいところに手が届く」ブログとなることを願いながら記事を書いています。

【Django】テンプレートフィルタを自作する方法について記述します

スポンサーリンク

テンプレートフィルタって便利ですよね。
Djangoの標準では様々なフィルタが用意されています。

自作の処理でも、テンプレートフィルタのように、
Djangoテンプレートのコンテキスト出力時にメソッドを挟み込めたら・・・と考えて調べていたのですが・・・

テンプレートフィルタは簡単に自作できることがわかりました!
早速その方法について記述していきます。

templatetagsディレクトリを作成する

・アプリケーションディレクトリと同じ階層に作成します
・__init__.pyを作成し、パッケージ化する必要があります

ディレクトリ構造としては、下記のようになります。

ROOT
`-- project_dir
   |
   |--project_name_dir
   |
   |--app_dir
   |
   |--templatetags
   |  | 
   |  |--__init__.py
   |  
   `

templatetagsディレクトリの中に任意の名前で、pythonソースを作成する

・今回はmy_filter.pyとしました

ROOT
`-- project_dir
   |
   |--project_name_dir
   |
   |--app_dir
   |
   |--templatetags
   |  | 
   |  |--__init__.py
   |  |-- my_filter.py
   `

フィルタの処理を書き、Djangoテンプレートから使えるようにする

引数で受け取ったキーのモデルデータが存在するかどうかを調べるフィルタです。
存在する場合はTrue, 存在しない場合はFalseを返す

# coding: utf-8
from django.template.defaultfilters import register

"""
 カスタムテンプレートフィルター
"""

# register.filterデコレータ
# register.filter('is_any_data_exists', is_any_data_exists')でも可
@register.filter
def is_any_data_exists(obj, pk):
    obj_list = obj.any_manytomany_field.filter(id=pk)
    if obj_list:
        return True
    else:
        return False

テンプレートから利用する

targetのmany_to_many_fieldに、
any_obj_pkのデータがあればTrue、なければFalseを返す

【具体例】
--------------------------------
ユーザ <- 既読一覧 -> 文書
--------------------------------
・文書(target)に対して、該当ユーザー(any_obj_pk)の既読データがあるかないかを確認する
 ⇒データがあれば、既読
 ⇒なければ未読
{% comment %}自作したフィルタを含むパッケージ名を指定{% endcomment %}
{% load my_filter %}

{% for target in target_list %}
<tr>
    <td>
        {% if not target|is_any_data_exists:any_obj_pk %}
            <small>未読</small>
        {% endif %}
        <a target="_blank" href="{% url 'project:any_view_name' obj_id=obj.id %}">{{ target.title }}</a>
    </td>
</tr>
{% endfor %}


別の画面で、同様のテンプレート処理を行いたい場合にすごく便利ですね。