2010-12-08 12 views
154

mag ich Zeichenfolge in django Template-Tag verketten wieWie verkette ich Strings in Django Templates?

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

Hier shop_name mein Variable ist, und ich möchte dies Weg mit dem Rest verketten.
Angenommen, ich habe shop_name=example.com

Und ich will Ergebnis shop/example.com/base.html

Antwort

307

Verwendung mit:

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

Ich war total verwirrt von dieser Antwort, da es das include-Tag anstelle des extend-Tags verwendet, aber anscheinend funktioniert es einfach, obwohl ich Ahsans eigene Antwort empfehlen würde, da es auch funktioniert und (meiner Meinung nach) semantisch korrekter ist und erhöht weniger Verwechslung – rednaw

+7

Dies kann funktionieren, sollte aber nicht als allgemeine Antwort auf die Verkettung von Strings in Django-Vorlagen betrachtet werden: http://stackoverflow.com/a/23783666/781695 – Medorator

+0

Wie in der Django-Dokumentation gesagt, "Strings, die können zu Ganzzahlen gezwungen werden summiert werden, nicht verkettet "So, zum Beispiel, wenn Sie die Primärschlüssel des Modells Objekt verketten wollen (kann nützlich sein, um eindeutige Cache-Schlüssel zu erstellen), funktioniert es nicht. – zen11625

0

Sie erweitern können variable Manipulation in django Vorlagen nicht. Sie haben zwei Optionen, entweder schreiben Sie Ihre eigenen Vorlage-Tag oder tun dies in Sicht,

+0

meine Anforderung ist es in nur Vorlagen zu tun, so Ansichten Option ist nicht hilfreich. Ich habe auch versucht, über benutzerdefinierte Vorlage Tag aber {% load concat%} sollte nach dem {% extend ....%} Tag. also wie kann ich es jetzt machen? – Ahsan

+0

Schreiben Sie ein extended_extens-Tag, das ein Zeichenfolgenformat und Argumente akzeptiert. –

+0

können Sie mir bitte ein Beispiel dafür geben, wie man benutzerdefinierte Tags für Standard-Tags schreibt? – Ahsan

1

Werfen Sie einen Blick auf die add filter.

Bearbeiten: Sie können Filter ketten, so dass Sie "Shop /" | hinzufügen können: Shopname | hinzufügen: "/ base.html". Aber das wird nicht funktionieren, weil es das Template-Tag ist, um Filter in Argumenten auszuwerten, und das nicht.

Ich denke, Sie können dies nicht in Vorlagen tun.

+0

das wird nicht funktionieren. Ich möchte meine Variable in der Mitte des Pfades hinzufügen. – Ahsan

+0

add filter summed nicht verketten nach django docs – Ahsan

+0

Die Dokumentation sagt "Zeichenfolgen, die zu ganzen Zahlen gezwungen werden können, werden summiert". Andere Zeichenfolgen werden verkettet. Aber das ist auch nicht wirklich wichtig, weil Sie den Filter nicht verwenden können :( –

0

extends hat keine Möglichkeit dafür. Legen Sie den gesamten Vorlagenpfad in eine Kontextvariable und verwenden Sie diese, oder kopieren Sie das vorhandene Vorlagen-Tag und ändern Sie es entsprechend.

+0

Danke für die Antwort! Für die Kontextvariable muss ich in view.py einstellen, was ich aufgrund meiner Projektanforderungen nicht tun kann. Und bitte geben Sie ein Beispiel für die zweite an – Ahsan

1

Aus der Dokumentation:

Dieser Tag kann auf zwei Arten verwendet werden:

  • {% extends "base.html" %} (mit Anführungszeichen) verwendet den Literalwert „base.html“, wie der Name der übergeordneten Vorlage zu erweitern .
  • {% extends variable %} verwendet den Wert der Variablen. Wenn die Variable eine Zeichenfolge ergibt, verwendet Django diese Zeichenfolge als Name der übergeordneten Vorlage. Wenn die Variable zu einem Vorlagenobjekt ausgewertet wird, verwendet Django dieses Objekt als übergeordnete Vorlage.

So scheint, als ob Sie einen Filter nicht verwenden können, um das Argument zu manipulieren. In der aufrufenden Ansicht müssen Sie entweder die Vorgängervorlage instanziieren oder eine Zeichenfolgenvariable mit dem richtigen Pfad erstellen und sie mit dem Kontext übergeben.

10

Ich habe die Ordner-Hierarchie geändert

/shop/shop_name/base.html Um /shop_name/shop/base.html

und dann würde unten arbeiten.

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

Jetzt ist es in der Lage, die base.html Seite zu erweitern.

66

nicht add für Strings Verwenden Sie, sollten Sie eine benutzerdefinierte Tag wie folgt definieren:

Erstellen Sie eine Datei: <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) 

und dann verwenden es als @ Steven sagt

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

Grund für die Vermeidung von add

Nach dem docs

Dieser Filter wird erste versuchen, beide Werte auf ganze Zahlen zu zwingen ... Strings, die auf ganze Zahlen umgewandelt werden können wird summiert, nicht verkettet ...

Wenn beide Variablen ganze Zahlen sind, wäre das Ergebnis unerwartet.

+0

Sollte das nicht @register.filter (name = 'addstr') sein? – seddonym

+0

Guter Fang, ich habe den Funktionsnamen in 'addstr' geändert. – Medorator

+0

Sieht so aus, als ob nur eine ganze Zahl ausreicht ... Danke dafür, es hätte mich ewig brauchen zu fangen! – mccc

1

@ Fehler Antwort ist grundsätzlich richtig, Sie sollten ein Template-Tag dafür verwenden. Allerdings ziehe ich einen etwas allgemeinere Template-Tag, dass ich jede Art von Operationen ähnlich wie diese ausführen kann:

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

und dann können Sie es so in der Vorlage verwenden:

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

Wie der Kommentar erwähnt, ist dieses Schablonen-Tag besonders nützlich für Informationen, die innerhalb einer Vorlage wiederholbar sind, aber Logik und andere Dinge erfordern, die Ihre Schablonen füllen, oder in Fällen, in denen Sie Daten zwischen Schablonen durch Blöcke wiederverwenden möchten:

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

und dann:

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

Kredit für den captureas Tag ist hier durch: https://www.djangosnippets.org/snippets/545/

1

Ich fand mit dem {% with %} Tag arbeiten ziemlich lästig zu sein. Stattdessen habe ich das folgende Template-Tag erstellt, das auf Strings und Integers angewendet werden sollte.

from django import template 

register = template.Library() 


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

dann den Template-Tag in Ihrer Vorlage laden an der Spitze des mit folgenden:

{% load concat_string %} 

Sie können es dann verwenden Sie die folgende Art und Weise:

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

ich persönlich diese gefunden viel sauberer arbeiten.

+0

hat für mich gearbeitet ... – cwhisperer

0

Siehe Concatenating Strings in Django Templates:

  1. Für frühere Versionen von Django:

    {{ "Mary hatte ein kleines" | String: "s Lamm" }}

"Mary hatte ein kleines Lamm."

  1. Else:

    {{ "Mary hatte ein wenig" | hinzu: "Lamm" }}

"Mary hatte ein kleines Lamm."