Jak połączyć łańcuchy w szablonach django?


191

Chcę połączyć łańcuch w znaczniku szablonu Django, na przykład:

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

Oto shop_namemoja zmienna i chcę połączyć to z resztą ścieżki.

Załóżmy, że mam shop_name=example.comi chcę, aby wynik przedłużył się shop/example.com/base.html.

Odpowiedzi:


380

Używać z:

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

2
Byłem całkowicie zdezorientowany tą odpowiedzią, ponieważ używa tagu włączenia zamiast tagu rozszerzenia, ale najwyraźniej po prostu działa. Chociaż poleciłbym własną odpowiedź Ahsana, ponieważ również działa i jest (moim zdaniem) semantycznie bardziej poprawna i powoduje mniej zamieszania.
— gitaarik

15
Może to działać, ale nie powinno być traktowane jako ogólna odpowiedź na łączenie ciągów w szablonach django. Zobacz stackoverflow.com/a/23783666/781695
— użytkownik

Jak powiedziano w dokumentacji Django: „Ciągi, które można przekonwertować na liczby całkowite, będą sumowane, a nie konkatenowane”. Na przykład, jeśli chcesz połączyć klucze podstawowe obiektu modelu (może to być przydatne do utworzenia unikalnego klucza pamięci podręcznej), nie praca.
— zen11625

Myślę, że to wcale nie ucieka shop_name, więc jest niebezpieczne.
— Flimm

Pamiętaj, jak już wspomniano, działa to tylko z łańcuchami! Jeśli tłumaczysz shop_nameprzed przekazaniem go do kontekstu w widoku, get_context_dataupewnij się, że jest tłumaczony przy użyciu ugettextzamiast ugettext_lazy.
— Kim

111

Nie używaj addciągów znaków, powinieneś zdefiniować niestandardowy tag, taki jak ten:

Utwórz plik: <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)

a następnie użyj go, jak mówi @Steven

{% load <appname>_extras %}

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

Powód unikania add:

Według dokumentów

Ten filtr najpierw spróbuje wymusić obie wartości na liczbach całkowitych ... Ciągi, które można wymusić na liczbach całkowitych, zostaną zsumowane, a nie połączone ...

Gdyby obie zmienne były liczbami całkowitymi, wynik byłby nieoczekiwany.


Czy nie powinno to być @ register.filter (name = 'addstr')?
— seddonym

6
Powinno to zostać oznaczone jako najlepsza odpowiedź, ponieważ działa poprawnie z wartościami, które Python może wymusić jako liczby całkowite.
— zen11625

2
Nie wiem, dlaczego nie jesteś tym, który jest najbardziej „podwyższony”, ponieważ tak jest twoja odpowiedź jest prawidłowa, sama „ add” po prostu nie używa str()na pierwszym miejscu i nie działała w ogóle dla mnie, podczas gdy twoje rozwiązanie działa bezbłędnie
— Olivier Pons

1
Twoja odpowiedź mnie uratowała!
— Ljubisa Livac

6
Pamiętaj, aby załadować własny filtr u góry pliku szablonu:{% load <appname>_extras %}
— Susanne Peng

13

Zmieniłem hierarchię folderów

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

a następnie poniżej będzie działać.

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

Teraz jest w stanie rozszerzyć stronę base.html.



3

Spójrz na addfiltr .

Edycja: możesz łączyć filtry, więc możesz to zrobić "shop/"|add:shop_name|add:"/base.html". Ale to nie zadziała, ponieważ ocena szablonu w argumentach zależy od tagu szablonu, a rozszerzenie nie.

Myślę, że nie możesz tego zrobić w szablonach.


to nie zadziała. chcę dodać moją zmienną na środku ścieżki.
— Ahsan,

dodaj filtr tylko zsumowany nie konkatenuje zgodnie z dokumentami django
— Ahsan

Dokumenty mówią „ciągi, które można wymusić na liczby całkowite, zostaną zsumowane”. Inne łańcuchy są łączone. Ale to tak naprawdę nie ma znaczenia, ponieważ nie można użyć filtra :(
— Daniel Hepper

2

Z dokumentów:

Tego znacznika można użyć na dwa sposoby:

  • {% extends "base.html" %} (z cudzysłowami) używa wartości literału „base.html” jako nazwy szablonu nadrzędnego, który ma zostać rozszerzony.
  • {% extends variable %}używa wartości zmiennej. Jeśli zmienna ma wartość ciągu, Django użyje tego ciągu jako nazwy szablonu nadrzędnego. Jeśli zmienna zostanie przekształcona w obiekt szablonu, Django użyje tego obiektu jako szablonu nadrzędnego.

Wygląda na to, że nie możesz użyć filtra do manipulowania argumentem. W widoku wywołującym musisz utworzyć instancję szablonu przodka lub utworzyć zmienną łańcuchową z poprawną ścieżką i przekazać ją z kontekstem.


1

Odpowiedź @ error jest zasadniczo poprawna, powinieneś do tego użyć tagu szablonu. Jednak wolę nieco bardziej ogólny tag szablonu, którego mogę używać do wykonywania wszelkiego rodzaju operacji podobnych do tego:

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

a następnie możesz użyć go w ten sposób w swoim szablonie:

{% captureas template %}shop/{{ shop_name }}/base.html{% endcaptureas %}
{% include template %}

Jak wspomniano w komentarzu, ten znacznik szablonu jest szczególnie użyteczny w przypadku informacji, które są powtarzalne w szablonie, ale wymagają logiki i innych rzeczy, które rozgromią twoje szablony lub w przypadkach, w których chcesz ponownie wykorzystać dane przekazywane między szablonami przez bloki:

{% captureas meta_title %}{% spaceless %}{% block meta_title %}
    {% if self.title %}{{ self.title }}{% endif %}
    {% endblock %}{% endspaceless %} - DEFAULT WEBSITE NAME
{% endcaptureas %}

i wtedy:

<title>{{ meta_title }}</title>
<meta property="og:title" content="{{ meta_title }}" />
<meta itemprop="name" content="{{ meta_title }}">
<meta name="twitter:title" content="{{ meta_title }}">

Kredyt na tag captureas należy się tutaj: https://www.djangosnippets.org/snippets/545/


1

Praca z {% with %}tagiem była dość kłopotliwa. Zamiast tego utworzyłem następujący znacznik szablonu, który powinien działać na ciągach i liczbach całkowitych.

from django import template

register = template.Library()


@register.filter
def concat_string(value_1, value_2):
    return str(value_1) + str(value_2)

Następnie załaduj tag szablonu do szablonu u góry, korzystając z następujących czynności:

{% load concat_string %}

Następnie możesz użyć go w następujący sposób:

<a href="{{ SOME_DETAIL_URL|concat_string:object.pk }}" target="_blank">123</a>

Osobiście uważam, że jest o wiele czystszy w pracy.


0

W szablonach django nie można manipulować zmiennymi. Masz dwie opcje: albo napisz własny tag szablonu, albo zrób to w widoku,


moim wymaganiem jest robienie tego tylko w szablonach, więc opcja widoków nie jest pomocna. Próbowałem także za pomocą niestandardowego tagu szablonu, ale {% load concat%} powinien znajdować się po tagu {% ext ....%}. więc jak mogę to teraz zrobić?
— Ahsan,

Napisz tag Extended_extends, który akceptuje format ciągu i argumenty.
— Paulo Scardine,

czy możesz podać przykład pisania niestandardowych tagów dla domyślnych?
— Ahsan,

0

extendsnie ma na to możliwości. Umieść całą ścieżkę szablonu w zmiennej kontekstowej i użyj jej, lub skopiuj istniejący znacznik szablonu i odpowiednio go zmodyfikuj.


dzięki za odpowiedź! dla zmiennej kontekstowej muszę ustawić w view.py, którego nie mogę ze względu na mój projekt. i proszę podać przykład drugiego.
— Ahsan,

0

I wiele konkatenacji:

from django import template
register = template.Library()


@register.simple_tag
def concat_all(*args):
    """concatenate all args"""
    return ''.join(map(str, args))

I w szablonie:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.