如何在 django 模板中连接字符串?

Posted

技术标签:

【中文标题】如何在 django 模板中连接字符串?【英文标题】:How to concatenate strings in django templates? 【发布时间】:2011-05-22 03:11:05 【问题描述】:

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

% extend shop/shop_name/base.html %

这里shop_name 是我的变量,我想将它与路径的其余部分连接起来。

假设我有shop_name=example.com,我希望结果扩展shop/example.com/base.html

【问题讨论】:

【参考方案1】:

用于:

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

【讨论】:

我完全被这个答案弄糊涂了,因为它使用包含标签而不是扩展标签,但显然它只是有效。虽然我会推荐 Ahsan 自己的答案,因为它也有效,并且(在我看来)在语义上更正确并且引起的混淆更少。 这可能有效,但不应被视为在 django 模板中连接字符串的一般答案。见***.com/a/23783666/781695 正如 Django 文档中的说法,“可以被强制转换为整数的字符串将被求和,而不是连接”所以,例如,如果你想连接模型对象的主键(可能对创建有用唯一的缓存键),它不起作用。 我觉得这根本逃不过shop_name,所以很危险。 请注意,如前所述,这仅适用于字符串!如果您在将shop_name 传递到视图的get_context_data 中的上下文之前翻译它,请确保使用ugettext 而不是ugettext_lazy 进行翻译。【参考方案2】:

不要对字符串使用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的原因:

根据docs

此过滤器将首先尝试将两个值强制转换为整数... 可以强制转换为整数的字符串将被求和,不连接...

如果两个变量恰好都是整数,结果会出乎意料。

【讨论】:

这应该被标记为最佳答案,因为可以正确使用可以被 Python 强制转换为整数的值。 我不知道为什么你不是最“向上”的人,因为它是 your 答案是正确的,单独的“add”只是不使用str() 排在第一位,根本没有对我有用,而您的解决方案却完美无缺 因为投票率高的答案是最简单的 - 并且,根据数据,正确。如果您有办法让数字出现在该字段中,那么就没有问题。话虽如此 - 这里有一个非常重要的提醒,必须考虑进入这个标签的数据。我为这两个答案 +1。 你的回答救了我! 记得在模板文件顶部加载自定义过滤器:% load &lt;appname&gt;_extras %【参考方案3】:

我已更改文件夹层次结构

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

然后下面会起作用。

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

现在它可以扩展 base.html 页面了。

【讨论】:

其他答案不允许与extends 使用串联,因为`扩展必须是模板中的第一个模板标签【参考方案4】:

参考Concatenating Strings in Django Templates:

    对于早期版本的 Django:

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

“玛丽有一只小羊羔。”

    其他:

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

“玛丽有一只小羊羔。”

【讨论】:

【参考方案5】:

您不需要编写自定义标签。只需评估彼此相邻的变量。

" shop name  other_path_var"

【讨论】:

通常最简单的答案是最好的。【参考方案6】:

看看add filter。

编辑:你可以链接过滤器,所以你可以做"shop/"|add:shop_name|add:"/base.html"。但这不起作用,因为它取决于模板标签来评估参数中的过滤器,而扩展则没有。

我猜你不能在模板中这样做。

【讨论】:

这行不通。我想在路径中间添加我的变量。 根据 django 文档仅添加过滤器而不是连接 文档说“可以强制转换为整数的字符串将被求和”。连接其他字符串。但这并不重要,因为你不能使用过滤器:(【参考方案7】:

这个怎么样!我们有first_namelast_name,我们要显示空间" " 分开。

% with first_name|add:' '|add:last_name as name %
    <h1> name </h1>
% endwith %

我们实际上在做的是:first_name + ' ' + last_name

【讨论】:

【参考方案8】:

来自文档:

这个标签有两种使用方式:

% extends "base.html" %(带引号)使用文字值“base.html”作为要扩展的父模板的名称。 % extends variable % 使用变量的值。如果变量的计算结果为字符串,Django 将使用该字符串作为父模板的名称。如果变量的计算结果为 Template 对象,Django 将使用该对象作为父模板。

看来您不能使用过滤器来操纵参数。在调用视图中,您必须实例化祖先模板或创建具有正确路径的字符串变量并将其与上下文一起传递。

【讨论】:

【参考方案9】:

@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/

【讨论】:

【参考方案10】:

我发现使用% 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>

我个人认为使用它要干净得多。

【讨论】:

【参考方案11】:

以及多重连接:

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 

【讨论】:

【参考方案12】:

您不能在 django 模板中进行变量操作。 你有两个选择,要么写你自己的模板标签,要么在视图中这样做,

【讨论】:

我的要求是仅在模板中执行此操作,因此视图选项没有帮助。我也尝试通过自定义模板标签,但 % load concat % 应该在 % extend .... % 标签之后。那我现在怎么办? 编写一个接受字符串格式和参数的扩展扩展标签。 你能给我一个如何为默认标签编写自定义标签的例子吗?【参考方案13】:

extends 对此无能为力。要么将整个模板路径放在上下文变量中并使用它,要么复制现有的模板标签并进行适当的修改。

【讨论】:

感谢您的回复!对于上下文变量,我必须在 view.py 中设置,由于我的项目要求,我无法设置。请举第二个例子。【参考方案14】:

在我的项目中,我是这样做的:

@register.simple_tag()
def format_string(string: str, *args: str) -> str:
    """
    Adds [args] values to [string]
    String format [string]: "Drew %s dad's %s dead."
    Function call in template: % format_string string "Dodd's" "dog's" %
    Result: "Drew Dodd's dad's dog's dead."
    """
    return string % args

这里,你想要连接的字符串和 args 可以来自视图,例如。

在模板中并使用您的案例:

% format_string 'shop/%s/base.html' shop_name as template %
% include template %

好消息是 format_string 可以在模板中用于任何类型的字符串格式化

【讨论】:

以上是关于如何在 django 模板中连接字符串?的主要内容,如果未能解决你的问题,请参考以下文章

模板标签内的Django字符串连接最佳实践

如何在 Django 模板中连接内容块? [复制]

ThinkPHP如何连接模板里面的字符串

自定义 Django 模板标签未加载到模板中

如何获取相关项目的列表并在 Django 中应用模板过滤器

给定数据库的 ODBC 连接字符串,如何修改我的 settings.py 以便我的 Django 应用程序连接到它?