Come concatenare le stringhe nei template di django?


191

Voglio concatenare una stringa in un tag modello Django, come:

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

Qui shop_name mia variabile e voglio concatenarla con il resto del percorso.

Supponiamo di avere shop_name=example.come voglio che il risultato si estenda shop/example.com/base.html.

Risposte:


380

Usa con:

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

2
Ero totalmente confuso da questa risposta in quanto utilizza il tag include invece del tag extender, ma a quanto pare funziona. Anche se consiglierei la risposta di Ahsan in quanto funziona ed è (secondo me) semanticamente più corretta e genera meno confusione.
gitaarik,

15
Questo potrebbe funzionare ma non dovrebbe essere considerato come una risposta generale per concatenare le stringhe nei template di django. Vedi stackoverflow.com/a/23783666/781695
utente

Come detto nella documentazione di Django, "Le stringhe che possono essere costrette a numeri interi verranno sommate, non concatenate" Quindi, ad esempio, se si desidera concatenare le chiavi primarie dell'oggetto modello (può essere utile per creare una chiave cache unica), non lavoro.
zen11625,

Penso che questo non sfugga shop_nameaffatto, quindi è pericoloso.
Flimm,

Attenzione, come già accennato, funziona solo con le stringhe! Se traduci shop_nameprima di passarlo al contesto in una vista get_context_dataassicurati che sia tradotto usando ugettextinvece di ugettext_lazy.
Kim

111

Non utilizzare addper le stringhe, è necessario definire un tag personalizzato come questo:

Crea un file: <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)

e poi usalo come dice @Steven

{% load <appname>_extras %}

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

Motivo per evitare add:

Secondo i documenti

Questo filtro tenterà innanzitutto di forzare entrambi i valori in numeri interi ... Le stringhe che possono essere forzate in numeri interi verranno sommate, non concatenate ...

Se entrambe le variabili fossero numeri interi, il risultato sarebbe inatteso.


Non dovrebbe essere @ register.filter (name = 'addstr')?
seddonimo,

6
Questo dovrebbe essere contrassegnato come migliore risposta perché funziona correttamente con valori che possono essere forzati da Python come numeri interi.
zen11625,

2
Non so perché non sei quello con il più "alto" perché è la tua risposta che è giusta, il " add" da solo non usa str()al primo posto e non ha funzionato affatto per me mentre la tua soluzione funziona perfettamente
Olivier Pons il

1
La tua risposta mi ha salvato!
Ljubisa Livac,

6
Ricorda di caricare il filtro personalizzato nella parte superiore del file modello:{% load <appname>_extras %}
Susanne Peng

13

Ho cambiato la gerarchia delle cartelle

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

e poi sotto avrebbe funzionato.

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

Ora è in grado di estendere la pagina base.html.


7

Fare riferimento a Concatenare le stringhe nei modelli Django :

  1. Per le versioni precedenti di Django:

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

"Mary ha un piccolo agnello."

  1. Altro:

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

"Mary ha un piccolo agnello."


3

Dai un'occhiata al addfiltro .

Modifica: puoi incatenare i filtri, così puoi farlo "shop/"|add:shop_name|add:"/base.html" . Ma ciò non funzionerà perché spetta al tag template valutare i filtri negli argomenti e non lo estende.

Immagino che non puoi farlo all'interno dei modelli.


questo non funzionerà. voglio aggiungere la mia variabile nel mezzo del percorso.
Ahsan,

aggiungi filtro solo sommato non concatenato secondo i documenti di django
Ahsan

I documenti dicono che "verranno sommate le stringhe che possono essere costrette a numeri interi". Altre stringhe sono concatenate. Ma non importa in ogni caso perché non puoi usare il filtro :(
Daniel Hepper l'

2

Dai documenti:

Questo tag può essere utilizzato in due modi:

  • {% extends "base.html" %} (con virgolette) utilizza il valore letterale "base.html" come nome del modello principale da estendere.
  • {% extends variable %}utilizza il valore di variabile. Se la variabile restituisce una stringa, Django userà quella stringa come nome del modello genitore. Se la variabile restituisce un oggetto Template, Django userà quell'oggetto come template genitore.

Quindi sembra che non puoi usare un filtro per manipolare l'argomento. Nella vista chiamante devi creare un'istanza del modello di antenato o creare una variabile stringa con il percorso corretto e passarla con il contesto.


1

La risposta di @ error è fondamentalmente corretta, per questo dovresti usare un tag template. Tuttavia, preferisco un tag modello leggermente più generico che posso utilizzare per eseguire qualsiasi tipo di operazione simile a questa:

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

e quindi puoi usarlo così nel tuo modello:

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

Come menzionato nel commento, questo tag modello è particolarmente utile per le informazioni ripetibili in un modello ma richiede logica e altre cose che bloccano i modelli o nei casi in cui si desidera riutilizzare i dati passati tra i modelli attraverso blocchi:

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

e poi:

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

Il credito per il tag captureas è dovuto qui: https://www.djangosnippets.org/snippets/545/


1

Ho trovato lavorare con il {% with %}tag per essere una seccatura. Invece ho creato il seguente tag template, che dovrebbe funzionare su stringhe e numeri interi.

from django import template

register = template.Library()


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

Quindi caricare il tag modello nel modello in alto utilizzando quanto segue:

{% load concat_string %}

È quindi possibile utilizzarlo nel modo seguente:

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

Personalmente ho trovato questo per essere molto più pulito con cui lavorare.


0

Non è possibile eseguire manipolazioni variabili nei modelli di django. Sono disponibili due opzioni: scrivere il proprio tag modello o farlo in vista,


il mio requisito è di farlo solo in modelli quindi l'opzione di visualizzazione non è utile. ho anche provato tramite il tag modello personalizzato ma {% load concat%} dovrebbe dopo il tag {% extended ....%}. quindi come posso farlo ora?
Ahsan,

Scrivi un tag extended_extends che accetta un formato stringa e argomenti.
Paulo Scardine,

puoi per favore darmi un esempio di come scrivere tag personalizzati per quelli predefiniti?
Ahsan,

0

extendsnon ha possibilità per questo. Inserire l'intero percorso del modello in una variabile di contesto e utilizzarlo oppure copiare il tag del modello esistente e modificarlo in modo appropriato.


grazie per la risposta! per la variabile di contesto devo impostare in view.py che non posso a causa dei miei requisiti di progetto. e per favore fai un esempio del secondo.
Ahsan,

0

E concatenazione multipla:

from django import template
register = template.Library()


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

E nel modello:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.