テンプレートコード内の変数の値を設定するにはどうすればよいですか?


216

テンプレートがあるとしましょう

<html>
<div>Hello {{name}}!</div>
</html>

テスト中に、このテンプレートを呼び出すPythonコードに触れずに変数の値を定義すると便利です。だから私はこのようなものを探しています

{% set name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>

このようなものがDjangoに存在しますか?

回答:


327

withテンプレートタグを使用できます。

{% with name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>
{% endwith %}

35
しかし、変数の値をwithで変更できますか?
David天宇Wong

2
with句でコンテナー(リストとタプルを試しました)を宣言できないようです
Vladislav Ivanishin

リストを宣言する必要がある場合は、make_listを使用します。 docs.djangoproject.com/en/1.9/ref/templates/builtins/#make-list
MrValdez

3
ジンジャは、それがジャンゴで動作しないのはなぜ{%set myvar = value%}だと言いますか?
ホルム

3
@holms DjangoはJinjaを使用しないため:-) docs.djangoproject.com/en/1.7/topics/templates
elimisteve

50

テンプレートタグを作成します。

アプリが含まれている必要がありますtemplatetagsと同じレベルで、ディレクトリをmodels.pyviews.py忘れてはいけない-これは、すでに存在して、それを作成していない場合など、__init__.pyディレクトリがPythonパッケージとして扱われていることを確認するために、ファイルを。

次のコードを使用してdefine_action.pytemplatetagsディレクトリ内に名前が付けられたファイルを作成します。

from django import template
register = template.Library()

@register.simple_tag
def define(val=None):
  return val

注:開発サーバーは自動的に再起動しません。templatetagsモジュールを追加した後、テンプレートでタグまたはフィルターを使用するには、サーバーを再起動する必要があります。


次に、テンプレートで次のようにコンテキストに値を割り当てることができます。

{% load define_action %}
{% if item %}

   {% define "Edit" as action %}

{% else %}

   {% define "Create" as action %}

{% endif %}


Would you like to {{action}} this item?

2
私の場合、ループの後、これは古い値を返します:(
holms

7
最新バージョンでは、assignment_tagの代わりにsimple_tagを使用できるようです(私にとってはうまくいきました)。
Katharine Osborne

このソリューションで私が得た問題は、値を上書きできないように見えることです。
JakubJabłoński

このテクニックを使用して、単なる値ではなくリストを設定する場合は、次を確認してください:stackoverflow.com/a/34407158/2193235
msb

あなたは整数として変数を設定していて、(例えば)それをインクリメントしたい場合は、使用する必要がありますadd{% define counter|add:1 as counter %}。他の操作についても同様です。
msb

35

すべてを「with」ブロックに入れる必要がない別の方法は、コンテキストに新しい変数を追加するカスタムタグを作成することです。のように:

class SetVarNode(template.Node):
    def __init__(self, new_val, var_name):
        self.new_val = new_val
        self.var_name = var_name
    def render(self, context):
        context[self.var_name] = self.new_val
        return ''

import re
@register.tag
def setvar(parser,token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    new_val, var_name = m.groups()
    if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SetVarNode(new_val[1:-1], var_name)

これにより、テンプレートに次のようなものを書くことができます:

{% setvar "a string" as new_template_var %}

これのほとんどはここから取られたことに注意してください


コンテキストに存在する他の変数に変数を割り当てるのはどうですか?また、別の注として、テンプレートがすでに存在するかどうかを確認せずにテンプレートが任意にコンテキスト変数を割り当てることを許可すると、セキュリティに影響を与える可能性があります。私の意見では、より賢明なアプローチは、変数を割り当てる前に、変数のコンテキストを確認することです
。–

if context.get(self.var_name):raise SuspiciousOperation( "Attempt to assign variable from template present present in context in context")
2015

27

ジョンが説明したようなトリックがあります。ただし、Djangoのテンプレート言語は設計上、変数の設定をサポートしていません(テンプレートについてはDjangoドキュメントの「哲学」ボックスを参照してください)。
このため、変数を変更するための推奨される方法、Pythonコードに触れることです。


7
ポインタをありがとう。設計者の観点からすると、ページを設計するときに、変数をすばやく設定してページのさまざまな状態をテストする方が簡単な場合があります。この方法を実行中のコードで使用することはお勧めしません。
アレクシス

2
"with"タグはdjango1.0で受け入れられます。だから彼らは最終的に彼らの哲学を修正しているように見えます:)。
エフゲニー

2
事実、 "with"タグはエイリアスのためだけのものです。これはパフォーマンス(および読みやすさ)に大きな影響を与える可能性がありますが、従来のプログラミング用語では実際には変数を設定していません。
ロブ・

12

これに対する最善の解決策は、カスタムを記述することですassignment_tag。このソリューションはwith、ロジックとスタイルを非常に明確に区別できるため、タグを使用するよりもクリーンです。

テンプレートタグファイルを作成することで起動します(例。appname/templatetags/hello_world.py):

from django import template

register = template.Library()

@register.assignment_tag
def get_addressee():
    return "World"

これで、get_addresseeテンプレートでテンプレートタグを使用できます。

{% load hello_world %}

{% get_addressee as addressee %}

<html>
    <body>
        <h1>hello {{addressee}}</h1>
    </body>
</html>

3
新しいDjangoバージョンを使用している人のために、今ではそのsimple_tagと呼ばれます 時間を節約して、「register ..」がコードで認識されない理由を理解してください...
kaya

11

おそらく、defaultテンプレートフィルターは2009年のオプションではありませんでした...

<html>
<div>Hello {{name|default:"World"}}!</div>
</html>

これは私が探していたものだと言わざるを得ません!と一緒に使用することもできます。{% with state=form.state.value|default:other_context_variable %}代わりに次のものother_context_variableを使用することもでき'string_value'ます
Saurav Kumar

しかし、それは印刷され、後で使用するために保存する必要があります
Holms

4

これは一般的に良い考えではありません。すべてのロジックをPythonで実行し、表示するテンプレートにデータを渡します。テンプレートは、ロジックを心配するのではなく、設計に携わっている人が設計に集中できるように、できるだけシンプルにする必要があります。

例をあげると、テンプレート内で派生情報が必要な場合は、それをpythonコードの変数に入れて、テンプレートに渡すことをお勧めします。


3

withステートメントを使用します。

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

この回答の最初の段落のコードを暗示することはできません。たぶん、テンプレート言語は古いフォーマットを非推奨にしたのでしょう。


2

テンプレートでは、次のようにすることができます:

{% jump_link as name %}
{% for obj in name %}
    <div>{{obj.helo}} - {{obj.how}}</div>
{% endfor %}

テンプレートタグに次のようなタグを追加できます:

@register.assignment_tag
def jump_link():
    listArr = []
    for i in range(5):
        listArr.append({"helo" : i,"how" : i})
    return listArr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.