djangoテンプレートで文字列を連結する方法は?


189

次のように、Djangoテンプレートタグ内の文字列を連結したいと思います。

{% extend shop/shop_name/base.html %}

これshop_nameが私の変数です。これを残りのパスと連結したいと思います。

私が持っていてshop_name=example.com、結果を拡張したいとしますshop/example.com/base.html

回答:


379

で使用:

{% with "shop/"|add:shop_name|add:"/base.html" as template %}
{% include template %}
{% endwith %}

2
この回答は、extendタグの代わりにincludeタグを使用しているので、完全に混乱しましたが、明らかに機能します。Ahsan自身の回答も機能し、(私の意見では)意味的にはより正確で、混乱が少ないため、私はAhsan自身の回答をお勧めします。
gitaarik 2013

15
これは機能するかもしれませんが、djangoテンプレート内の文字列を連結するための一般的な回答とは見なされません。stackoverflow.com/a/23783666/781695を
ユーザー、

Djangoのドキュメントにあるように、「整数に強制変換できる文字列は連結ではなく合計されます」したがって、たとえば、モデルオブジェクトの主キーを連結する場合(一意のキャッシュキーの作成に役立つ場合があります)、作業。
zen11625 2015

これはまったく逃げshop_nameられないと思いますので危険です。
Flimm

すでに述べたように、これは文字列でのみ機能することに注意してください!shop_nameビューのコンテキストに渡す前に翻訳する場合は、の代わりにget_context_dataを使用して翻訳してください。ugettextugettext_lazy
キム

111

使わない add文字列にようなカスタムタグを定義する必要があります。

ファイルを作成します。 <appname>\templatetags\<appname>_extras.py

from django import template

register = template.Library()

@register.filter
def addstr(arg1, arg2):
    """concatenate arg1 & arg2"""
    return str(arg1) + str(arg2)

@Stevenが言うようにそれを使用します

{% load <appname>_extras %}

{% with "shop/"|addstr:shop_name|addstr:"/base.html" as template %}
    {% include template %}
{% endwith %}

回避する理由add

ドキュメントによると

このフィルターは、最初に両方の値を整数に強制変換しようとします...整数に強制変換できる文字列は、連結されずに合計されます...

両方の変数が偶然整数である場合、結果は予期しないものになります。


@ register.filter(name = 'addstr')にすべきではありませんか?
セドニム2014

6
Pythonによって整数として強制変換できる値を正しく処理するため、これはベストアンサーとしてマークする必要があります。
zen11625 2015

2
あなたの答えが正しいので、なぜあなたが最も「上」ではないのかわかりaddません。「」だけではそもそも使用str()できず、まったく機能しませんでしたが、解決策は完璧に機能します
オリビエ・ポンス

1
あなたの答えは私を救った!
リュビサリバック

6
お使いのテンプレートファイルの先頭にカスタムフィルタをロードすることを忘れないでください:{% load <appname>_extras %}
スザンヌ鵬

13

フォルダ階層を変更しました

/shop/shop_name/base.html To /shop_name/shop/base.html

そして以下はうまくいくでしょう。

{% extends shop_name|add:"/shop/base.html"%} 

これで、base.htmlページを拡張できます。


7

Djangoテンプレートでの文字列の連結を参照してください:

  1. Djangoの以前のバージョンの場合:

    {{ "Mary had a little"|stringformat:"s lamb." }}

「メアリーは小さな子羊を持っていました。」

  1. そうしないと:

    {{ "Mary had a little"|add:" lamb." }}

「メアリーは小さな子羊を持っていました。」


3

addフィルターを見てください。

編集:フィルターをチェーンできるので、そうすることができます"shop/"|add:shop_name|add:"/base.html"。しかし、引数でフィルターを評価するのはテンプレートタグ次第であり、拡張は機能しないため、これは機能しません。

テンプレート内でこれを行うことはできないと思います。


これはうまくいきません。パスの途中に変数を追加したい。
Ahsan

django docsによると、連結のみではなく連結のみのフィルターを追加します
Ahsan

ドキュメントは、「整数に強制変換できる文字列は合計される」と言っています。他の文字列は連結されます。しかし、フィルターを使用できないため、とにかく問題はありません:(
Daniel Hepper

2

ドキュメントから:

このタグは次の2つの方法で使用できます。

  • {% extends "base.html" %} (引用符付き)拡張する親テンプレートの名前としてリテラル値「base.html」を使用します。
  • {% extends variable %}変数の値を使用します。変数が文字列に評価される場合、Djangoはその文字列を親テンプレートの名前として使用します。変数がTemplateオブジェクトに評価される場合、Djangoはそのオブジェクトを親テンプレートとして使用します。

つまり、引数を操作するためにフィルターを使用できないようです。呼び出しビューでは、祖先テンプレートをインスタンス化するか、正しいパスを使用して文字列変数を作成し、コンテキストとともに渡す必要があります。


1

@errorの答えは基本的に正しいです。これにはテンプレートタグを使用する必要があります。ただし、私はこれに似たあらゆる種類の操作を実行するために使用できる少し一般的なテンプレートタグを好みます。

from django import template
register = template.Library()


@register.tag(name='captureas')
def do_captureas(parser, token):
    """
    Capture content for re-use throughout a template.
    particularly handy for use within social meta fields 
    that are virtually identical. 
    """
    try:
        tag_name, args = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("'captureas' node requires a variable name.")
    nodelist = parser.parse(('endcaptureas',))
    parser.delete_first_token()
    return CaptureasNode(nodelist, args)


class CaptureasNode(template.Node):
    def __init__(self, nodelist, varname):
        self.nodelist = nodelist
        self.varname = varname

    def render(self, context):
        output = self.nodelist.render(context)
        context[self.varname] = output
        return ''

テンプレートで次のように使用できます。

{% captureas template %}shop/{{ shop_name }}/base.html{% endcaptureas %}
{% include template %}

コメントで言及されているように、このテンプレートタグは、テンプレート全体で繰り返し使用できるが、テンプレートを強化するロジックやその他のものが必要な場合、またはテンプレートを介してブロック間で渡されるデータを再利用する場合に特に便利です。

{% captureas meta_title %}{% spaceless %}{% block meta_title %}
    {% if self.title %}{{ self.title }}{% endif %}
    {% endblock %}{% endspaceless %} - DEFAULT WEBSITE NAME
{% endcaptureas %}

その後:

<title>{{ meta_title }}</title>
<meta property="og:title" content="{{ meta_title }}" />
<meta itemprop="name" content="{{ meta_title }}">
<meta name="twitter:title" content="{{ meta_title }}">

captureasタグのクレジットの期限はこちら:https : //www.djangosnippets.org/snippets/545/


1

私は働いた{% with %}、非常に面倒であることをタグ。代わりに、次のテンプレートタグを作成しました。これは、文字列と整数で機能するはずです。

from django import template

register = template.Library()


@register.filter
def concat_string(value_1, value_2):
    return str(value_1) + str(value_2)

次に、以下を使用して上部のテンプレートにテンプレートタグをロードします。

{% load concat_string %}

その後、次のように使用できます。

<a href="{{ SOME_DETAIL_URL|concat_string:object.pk }}" target="_blank">123</a>

私は個人的にこれを扱うのがずっときれいだと思いました。


0

djangoテンプレートでは変数を操作できません。独自のテンプレートタグを作成するか、ビューでこれを行うかの2つのオプションがあります。


私の要件は、テンプレートのみでそれを行うことですので、ビューオプションは役に立ちません。また、カスタムテンプレートタグを使用して試しましたが、{%load concat%}は{%extend ....%}タグの後に配置する必要があります。それで、どうすれば今それを行うことができますか?
Ahsan

文字列形式と引数を受け入れるextended_extendsタグを記述します。
Paulo Scardine、2010

デフォルトタグのカスタムタグの記述方法の例を教えてください。
Ahsan

0

extendsこのための機能はありません。テンプレートパス全体をコンテキスト変数に入れて使用するか、既存のテンプレートタグをコピーして適切に変更します。


返信ありがとうございます!コンテキスト変数については、プロジェクトの要件のためにできないview.pyで設定する必要があります。2番目の例を挙げてください。
Ahsan

0

そして、複数の連結:

from django import template
register = template.Library()


@register.simple_tag
def concat_all(*args):
    """concatenate all args"""
    return ''.join(map(str, args))

そしてテンプレートで:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.