Django:Templateから独自関数を呼び出して利用する方法

Django:Templateから独自関数を呼び出して利用する方法

Django:Templateから独自関数を呼び出して利用する方法

Templateに渡した引数をPython独自関数に投げて値を返してもらい、表示を変更する。
こんな記事を見かけ、「へぇ~そんなことできるんだ」と思いやってみました。

下準備

テンプレートで独自関数を使うためにはいくつかの準備が必要です。

  1. アプリケーションディレクトリ直下に【templatetags】というディレクトリを作成
  2. templatetagsディレクトリに load 呼出し名.pyのファイルを作成 ※ここにコードを記載していきます。
  3. templatetagsディレクトリに__init__.pyを配置 ※ 何も書かなくてもOKな様です。
  4. templatetags内を設定したらDjangoを再起動 ※Dockerの場合はコンテナリビルドでもOKです。

後はTemplateで呼び出し用コードを記載すれば機能します。
templatetagsというディレクトリ名についてはDjangoの命名規制だそうです。
なので、配置場所とディレクトリ名は固定です。

コードの書き方について

  1. from django import template をUseする
  2. おまじない [ register = template.Library() ] を記載する
  3. 関数名を [ @register.filter(name=”関数名”) ] として記載する
  4. 関数は普通に [ def 関数名 ] で書き始める
  5. return は1つだけ ※ Template内でリストをこね回せないので

サンプルコード

■app\templatetags\tag_library.py

独自関数の呼出しの手順

  1. 独自関数を使うTemplateに {% load 呼出し名 %}を配置
  2. 値を返す位置に {{ 引数| 関数名:第2引数 }} を記載

必要なのはこの2手だけです。

呼出しのサンプル

■app\template\index.html ※views.pyからSkillsという引数でDataFrameを渡している

Skills (DataFrame)

      days
MySQL      2036
JavaScript   1976
PHP     1974
Python   1914

こんなコードで帰ってきます。

これはこれで面白い。でも新たな悩みが出来ました。

JavaScriptと独自関数の使い分けって何を基に考えればいい?

【TemplateSyntaxError ‘呼出し名’ is not a registered tag library】が発生したら

Djangoからtemplatetagsディレクトリが見えていない時、このエラーが発生します。
そんな時は下の4点を確認しましょう。

  1. templatetagsディレクトリにスペルミスはないか
  2. templatetagsディレクトリはアプリ直下に配置されているか
  3. loadするファイルにregisterアノテーション(@register)を付けているか
  4. Djangoの再起動はしたか

私の場合はDockerコンテナのリビルドをしたら解消しました。
なので、ディレクトリを作成してpyファイルをソコに納めてもDjangoが認識してくれない事があるのは確実です。

また調べていた時に「INSTALLED_APPSにパスを通す必要がある」との情報がありましたが、コレは無くても大丈夫なようです。
(私の環境では記載したら500エラーが発生しました。)

独自関数は同一ファイル内にいくつでも格納できる

@ragister.filter(name=”hoge”)とすれば {{ 引数|hoge }}で利用することになります。
こんな感じで複数登録しても全く問題ありません。

同じ事ならJavaScriptでもできるJSと独自関数の棲み分けは?

そう、同じことはJavaScriptでもできます。
JavaScriptと独自関数の違いと言えばTemplateに渡す引数の形。
JavaScriptではDataFrame型を渡されても処理できないので、リストに変更しておく必要があります。

# 渡す値
js_data = [[‘MySQL’, 2036], [‘JavaScript’, 1976], [‘PHP’, 1974], [‘python’, 1914]]

どうすみ分ける?

明確な分岐ポイントが少なく最適な棲み分け方についてはとても難しい議題です。
ただ1点、独自関数の方は返却できる値が1つに限られるという点が挙げられます。
※複数の値を返すことはできるが受け取り(展開)が面倒

JS側は今回の例では 『id=Range』に対して『ひとまとまり』にしたコードを返却しましたが『class=Range』にすれば回数と合わせて複数の値を適用することができます。
なので、Template側でforループを使っていてもJavaScriptが使えないなんてことはありません。

個人的にはこんな棲み分けで考えています。

  • returnで複数の値を扱いたい時は【JavaScript】
  • DataFrameで渡す必要があるときは【独自関数】
  • デザイン的な動作を考慮する場合は【JavaScript】
  • スクリプトの統一性を考えるなら【独自関数】
  • 他のシステムでも流用したいパーツであれば【JavaScript】
  • CRUDに絡むパーツであれば【独自関数】
  • 計算結果をもとにもう一度モデルにアクセスしたい【独自関数】

でもまぁ、ここら辺は人それぞれかなと思います。

今回使って面白かった関数

  • 少数の値を整数部分と小数点以下の部分に分ける関数【modf】⇒参考:こちら / こちら

少数を整数部分と少数点以下の部分に分ける関数があるというのは知りませんでした。

「少数を小数点以下切り捨てして変数に格納して、それをもとの少数から減算して」というルートで実装しようとしていたので「まさか1行で出来るとは!」という感じでした。

いやぁ~、知らないだけで色々あるんですよね。

ちなみに【Round】いつも忘れて調べます。検索結果が出てきて「コレ!」ってわかるんだからいい加減に脳内書庫から「スッ」と取り出したいものだと強く思います。

まとめ

Templateを中心に考えると操作しやすいのは独自関数の方になると思います。
で、汎用性で考えるとJavaScriptかなと。