如何串联Django模板中的字符串?


189

我想在Django模板标签中连接一个字符串,例如:

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

shop_name是我的变量,我想将其与其余路径连接起来。

假设我有shop_name=example.com并且我想要结果扩展shop/example.com/base.html

Answers:


379

用于:

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

2
这个答案让我完全困惑,因为它使用include标记而不是extend标记,但是显然它可以正常工作。尽管我会推荐Ahsan自己的答案,因为它也行得通,而且(在我看来)在语义上更正确,也减少了混乱。
gitaarik

15
这可能有效,但不应视为在Django模板中连接字符串的一般答案。请参阅stackoverflow.com/a/23783666/781695
用户

就像Django文档中所说的那样,“可以强制转换为整数的字符串将被求和,而不是连接在一起”。因此,例如,如果您要连接模型对象的主键(可能对创建唯一的缓存键很有用),则不会工作。
zen11625 2015年

我认为这根本无法逃脱shop_name,所以很危险。
Flimm

请注意,正如已经提到的,这仅适用于字符串!如果您shop_name在将其传递到视图的上下文之前get_context_data进行翻译,请确保使用ugettext而不是对其进行翻译ugettext_lazy
金(Kim)

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')吗?
seddonym 2014年

6
应该将其标记为最佳答案,因为正确使用可以由Python强制为整数的值。
zen11625 2015年

2
我不知道您为什么不是“最多”的人,因为这是正确答案,仅“ add”一字str()不用对我根本没有用,而您的解决方案则完美无缺
Olivier Pons

1
您的回答救了我!
Ljubisa Livac '18 -4-5

6
记得将自定义过滤器加载到模板文件的顶部:{% load <appname>_extras %}
Susanne Peng

13

我已经更改了文件夹层次结构

/shop/shop_name/base.html 转到 /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 2010年

根据django文档,添加过滤器的总和不是串联的
Ahsan 2010年

文档说“将可强制转换为整数的字符串相加”。其他字符串是串联的。但这实际上并不重要,因为您不能使用过滤器:(
Daniel Hepper 2010年

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模板中执行变量操作。您有两种选择,要么编写自己的模板标记,要么在视图中执行此操作,


我的要求是仅在模板中执行此操作,因此“视图”选项没有帮助。我也尝试通过自定义模板标记进行操作,但{%load concat%}应该在{%extended ....%}标记之后。所以我现在该怎么办?
Ahsan 2010年

编写一个extended_extends标签,该标签接受字符串格式和参数。
Paulo Scardine 2010年

您能否举一个例子说明如何为默认标签编写自定义标签?
Ahsan 2010年

0

extends没有为此的设施。可以将整个模板路径放在上下文变量中并使用它,或者复制现有的模板标记并对其进行适当的修改。


感谢thanx!对于上下文变量,我必须在view.py中设置,由于我的项目要求,我不能设置它。请举第二个例子。
Ahsan 2010年

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 }}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.