結論
オブジェクトにdo_not_call_in_templates = True
を付与する
class SampleCallableClass:
do_not_call_in_templates = True
def __call__(self):
pass
def sample_method(self):
pass
sample_method.do_not_call_in_templates = True
概要
Djangoテンプレートでは、ある変数が呼び出し可能かどうかをまずチェックし、呼び出し可能であれば引数無しで呼び出します。
例えば、{{ Hoge.fuga }}
において、Hoge
が呼び出し可能である場合、これは{{ Hoge().fuga }}
のように評価されます。
しかしながら、呼び出し可能なオブジェクトを呼び出さずにそのプロパティにアクセスしたいという場合があります。
例えばHoge
が列挙型である場合は引数無しでの呼び出しHoge()
が出来ずにエラーとなり、残りの要素.fuga
は評価されず、最終的に空の文字列が出力されます。
こうした状況について、公式ドキュメントには以下のように記述されています。
Occasionally you may want to turn off this feature for other reasons, and tell the template system to leave a variable uncalled no matter what. To do so, set a
do_not_call_in_templates
attribute on the callable with the valueTrue
. The template system then will act as if your variable is not callable (allowing you to access attributes of the callable, for example).https://docs.djangoproject.com/en/3.0/ref/templates/api/#variables-and-lookups
呼び出し可能オブジェクトにdo_not_call_in_templates = True
を付与することで、呼び出し可能でないかのように振る舞わせることが出来るようになります。
余談
Django3.0で追加されたChoices
の実装を読んでいた際に、ChoicesMeta
の__new__
メソッドにdo_not_call_in_templates
が使われているのを見つけて記事にしてみました。