Як об'єднати рядки в шаблони джанго?


191

Я хочу об'єднати рядок у тег шаблону Django, наприклад:

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

Ось shop_nameмоя змінна, і я хочу поєднати це з рештою шляху.

Припустимо, у мене є shop_name=example.comі я хочу, щоб результат розширився shop/example.com/base.html.

Відповіді:


380

Використовувати з:

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

2
Ця відповідь мене повністю збентежила, оскільки він використовує тег включення замість тегу розширення, але, мабуть, він просто працює. Хоча я б порекомендував власну відповідь Аксана, оскільки це також працює і є (на мою думку) семантично правильнішим і викликає меншу плутанину.
gitaarik

15
Це може працювати, але не слід розглядати як загальну відповідь на об'єднання рядків у шаблони джанго. Дивіться stackoverflow.com/a/23783666/781695
користувач

Як говориться в документації Django, "Рядки, які можна примусити до цілих чисел, будуть підсумовані, а не об'єднані". Так, наприклад, якщо ви хочете об'єднати первинні ключі об'єкта моделі (можуть бути корисні для створення унікального ключа кешу), це не робота.
zen11625

Я думаю, що це взагалі не виходить shop_name, тому це небезпечно.
Flimm

Будьте в курсі, як уже згадувалося, це працює лише з рядками! Якщо ви перекладете, shop_nameперш ніж передати його в контекст у представленні, get_context_dataпереконайтеся, що він переведений за допомогою, ugettextа не ugettext_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')?
седонім

6
Це слід позначити як найкращу відповідь, оскільки правильно працювати зі значеннями, які можуть бути примушені Python як цілі числа.
zen11625

2
Я не знаю , чому ти не один з найбільш «вгору» , тому що це ваш відповідь , який правильно, « add» в поодинці просто не використовувати str()в першу чергу , а не працювати на всіх для мене в той час як ваше рішення працює безвідмовно
Олів'є Понс

1
Ваша відповідь мене врятувала!
Любіса Лівак

6
Не забудьте завантажити власний фільтр у верхній частині файлу шаблону:{% load <appname>_extras %}
Сьюзенн Пенг,

13

Я змінив ієрархію папок

/shop/shop_name/base.html До /shop_name/shop/base.html

а потім би працювало нижче.

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

Тепер його можливість розширити сторінку base.html.



3

Погляньте на addфільтр .

Редагувати: Ви можете ланцюг фільтрів, щоб ви могли це зробити "shop/"|add:shop_name|add:"/base.html". Але це не буде працювати, оскільки оцінювати фільтри в аргументах залежить від тега шаблону, а розширення - ні.

Я думаю, ви не можете зробити це в шаблонах.


це не спрацює. я хочу додати свою змінну в середині шляху.
Ахсан

додати фільтр лише підсумований не з’єднати згідно з django docs
Ahsan

Документи кажуть, що "рядки, які можна примусити до цілих чисел, будуть підсумовані". Інші рядки з'єднані. Але це насправді не має значення, тому що ви не можете використовувати фільтр :(
Даніель Хеппер

2

З документів:

Цей тег можна використовувати двома способами:

  • {% extends "base.html" %} (з лапками) використовує буквальне значення "base.html" як ім'я батьківського шаблону для розширення.
  • {% extends variable %}використовує значення змінної. Якщо змінна оцінює рядок, Django використовуватиме цей рядок як ім'я батьківського шаблону. Якщо змінна визначається об'єктом Template, Django використовуватиме цей об'єкт як батьківський шаблон.

Так здається, що ви не можете використовувати фільтр для маніпулювання аргументом. У вікні виклику вам потрібно або створити шаблон предка або створити змінну рядка з правильним шляхом та передати його контексту.


1

@ відповідь про помилку принципово правильна, для цього вам слід використовувати тег шаблону. Однак я віддаю перевагу трохи більш загальному тегу шаблону, який я можу використовувати для виконання будь-яких подібних операцій:

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

Кредит за тег захоплення належить тут: 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

Ви не можете робити маніпуляції зі змінними в шаблонах джанго. У вас є два варіанти: або написати власний тег шаблону, або зробити це з огляду,


моя вимога - робити це лише в шаблонах, щоб варіант перегляду не був корисним. Я також спробував користуватися тегом шаблону, але {% load concat%} повинен після тегу {% extension ....%}. так як я можу це зробити зараз?
Ахсан

Напишіть тег розширеного_поширення, який приймає формат рядка та аргументи.
Пауло Скардін

Ви можете, будь ласка, надати мені приклад, як писати власні теги для типових?
Ахсан

0

extendsне має для цього можливості. Або покладіть весь шлях до шаблону в змінну контексту і скористайтеся цим, або скопіюйте тег шаблону та змініть його відповідним чином.


дякую за відповідь! для змінної контексту я повинен встановити в view.py, що я не можу через мою вимогу проекту. і, будь ласка, наведіть приклад другого.
Аксан

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 }}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.