ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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


S
Steven

用于:

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

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

不要将 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 <appname>_extras %}
A
Ahsan

我更改了文件夹层次结构

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

然后下面会起作用。

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

现在它能够扩展 base.html 页面。


其他答案不允许使用与 extends 的连接,因为`扩展必须是模板中的第一个模板标签
D
Daniel Holmes

参考Concatenating Strings in Django Templates

对于早期版本的 Django:{{ "Mary had a little"|stringformat:"s lamb." }}

“玛丽有只小羊羔。”

其他:{{“玛丽吃了一点”|加:“羊肉。” }}

“玛丽有只小羊羔。”


D
David Jay Brady

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

"{{ shop name }}{{ other_path_var}}"

最简单的答案往往是最好的答案。
这是这里最简单也是最好的答案!
c
cezar

看看add filter

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

我猜你不能在模板中做到这一点。


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

这个怎么样!我们有 first_namelast_name,我们希望将空格 " " 分开。

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

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


U
User97693321

从文档:

此标签可以通过两种方式使用:

{% extends "base.html" %} (带引号)使用文字值 "base.html" 作为要扩展的父模板的名称。

{% extends variable %} 使用变量的值。如果变量的计算结果为字符串,Django 将使用该字符串作为父模板的名称。如果变量的计算结果为 Template 对象,Django 将使用该对象作为父模板。

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


B
Bono

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

我个人发现使用它要干净得多。


K
K3TH3R

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


G
Gassan

和多重连接:

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 }}

d
damir

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


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

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


谢谢回复!对于上下文变量,我必须在 view.py 中设置,由于我的项目要求,我无法设置。请举第二个例子。
J
Jailton Silva

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

@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 可以重复用于模板中的任何类型的字符串格式