Как объединить строки в шаблонах Django?
Я хочу объединить строку в теге шаблона Django, как
{% extend shop/shop_name/base.html %}
Здесь shop_name - моя переменная, и я хочу объединить это с остальной частью пути.
Предположим, у меня есть shop_name=example.com
И я хочу результат расширить shop/example.com/base.html
15 ответов
Использовать с:
{% with "shop/"|add:shop_name|add:"/base.html" as template %}
{% include template %}
{% endwith %}
Не использовать 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
{% with "shop/"|addstr:shop_name|addstr:"/base.html" as template %}
{% include template %}
{% endwith %}
Причина избеганияadd
Согласно документам
Этот фильтр сначала попытается привести оба значения к целым числам... Строки, которые можно привести к целым числам, будут суммироваться, а не объединяться...
Если обе переменные окажутся целыми числами, результат будет неожиданным.
Вам не нужно писать собственный тег. Просто оцените вары рядом друг с другом.
"{{ shop name }}{{ other_path_var}}"
Я изменил иерархию папок
/shop/shop_name/base.html To /shop_name/shop/base.html
и тогда ниже будет работать.
{% extends shop_name|add:"/shop/base.html"%}
Теперь можно расширять страницу base.html.
См. Конкатенация строк в шаблонах Django:
Для более ранних версий Django:
{{"У Мэри было немного"|stringformat:"Агнец". }}
"У Мэри был маленький ягненок."
Else:
{{"У Мэри было немного" | добавить: "ягненок". }}
"У Мэри был маленький ягненок."
И множественная конкатенация:
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 }}
Посмотрите на add
фильтр.
Изменить: вы можете цепочки фильтров, чтобы вы могли сделать "shop/"|add:shop_name|add:"/base.html"
, Но это не сработает, потому что это зависит от тега шаблона для оценки фильтров в аргументах, а расширение не работает.
Я думаю, вы не можете сделать это в шаблонах.
Как насчет этого! У нас есть
first_name
а также
last_name
, которому мы хотим отобразить пробел
" "
разделены.
{% with first_name|add:' '|add:last_name as name %}
<h1>{{ name }}</h1>
{% endwith %}
На самом деле мы делаем следующее:
first_name + ' ' + last_name
Из документов:
Этот тег можно использовать двумя способами:
{% extends "base.html" %}
(с кавычками) использует литеральное значение "base.html" в качестве имени родительского шаблона для расширения.{% extends variable %}
использует значение переменной. Если переменная оценивается как строка, Django будет использовать эту строку в качестве имени родительского шаблона. Если переменная оценивается как объект Template, Django будет использовать этот объект в качестве родительского шаблона.
Похоже, вы не можете использовать фильтр для управления аргументом. В вызывающем представлении вы должны либо создать экземпляр шаблона предка, либо создать строковую переменную с правильным путем и передать ее в контексте.
Я нашел работу с {% 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>
Лично я нашел, что с этим работать намного чище.
Вы не можете делать переменные в шаблонах Django. У вас есть два варианта: либо написать свой собственный тег шаблона, либо сделать это на виду,
Ответ @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/
В своем проекте я сделал это так:
@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
Здесь строка, которую вы хотите объединить, и аргументы могут поступать, например, из представления.
В шаблоне и в вашем случае:
{% format_string 'shop/%s/base.html' shop_name as template %}
{% include template %}
Приятно то, что format_string можно повторно использовать для любого типа форматирования строк в шаблонах.
extends
не имеет возможности для этого. Либо поместите весь путь шаблона в контекстную переменную и используйте его, либо скопируйте существующий тег шаблона и измените его соответствующим образом.
В моем случае мне нужно было конкатенировать, чтобы отправить строку, объединенную параметром, в simple_tag, и мне не нужен with, который экономит 2 строки:
{% method firstParam "stringSecondParam="|add:valueSecondParam thirdParam as result %}
В этом случае решение проблемы будет таким: "string="|add:object