[bottle] Variabler Template-Name mit %include

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Hallo,

ich habe ein main-Template in das ich mit ``include`` weitere Templates einbinden möchte. Leider kann ich scheinbar kein variablen Template-Namen übergeben.

Der folgende Code funktioniert:

Code: Alles auswählen

%include template_name test="TEST"
Folgender Code gibt mir eine Fehlermeldung:

Code: Alles auswählen

%name="template_name"
%include name test="TEST"

Code: Alles auswählen

Template ('name') not found.
Kann mir jemand erklären, was ich falsch mache, und wie man sowas mit "bottle" stattdessen umsetzen würde.

Grüße
Gerrit
Sync32
User
Beiträge: 141
Registriert: Mittwoch 27. Januar 2010, 12:42

Hast das Template in einem extra Ordner (z.B. tempaltes/...) ?

Versuch mal ' ' zu benutzen anstatt " "

Beispiel:

Code: Alles auswählen

%include header_template title='Hello World'
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also laut Doku anscheinend gar nicht. Zumindest steht da nicht explizit, dass der Template Name interpretiert wird

Mit jinja2 sollte das gehen: http://jinja.pocoo.org/2/documentation/ ... te-objects (wenn ich die Doku hier richtig verstehe).

Allerdings verstehe ich den Use-Case dahinter nicht so wirklich... wäre ja mal interessant zu wissen, wie Deine Rahmenbedingungen aussehen?

@sync32: Wo ist da jetzt der Unterschied zum Code von gkuhl?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from random import shuffle
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates'))

def main():
    template = env.get_template('inhalt.txt')
    masters = map(env.get_template, ("layout_a.txt", "layout_b.txt"))
    shuffle(masters)
    print template.render(parent=masters[0])


if __name__ == "__main__":
    main()
mit den Templates für zwei Master-Layouts

Code: Alles auswählen

Bin das große, tolle A-Layout...
{% block inhalt %}
nix :-)
{% endblock %}
... und ende hier :-)
und

Code: Alles auswählen

Bin das große, tolle B-Layout...
{% block inhalt %}
nix :-)
{% endblock %}
... und ende hier :-)
sowie für das Inhalt verantwortliche:

Code: Alles auswählen

{% extends parent %}
{% block content %}
Mal gucken, obs klappt
{% endblock %}
qed. :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Sync32 hat geschrieben:Hast das Template in einem extra Ordner (z.B. tempaltes/...) ?
Die Templates existieren und werden auch gefunden, wenn ich den Namen direkt angebe. Ich möchte aber gerne den Namen als String übergeben, was nicht geht, weil bottle den Bezeicher des Strings als template-name missinterpretiert.
Hyperion hat geschrieben:Also laut Doku anscheinend gar nicht. Zumindest steht da nicht explizit, dass der Template Name interpretiert wird. [...] Allerdings verstehe ich den Use-Case dahinter nicht so wirklich... wäre ja mal interessant zu wissen, wie Deine Rahmenbedingungen aussehen?
In der Dokumentation bin ich auch nicht fündig geworden. Zum Hintergrund: Ich schreibe ein kleines Programm um die wissenschaftliche Daten meiner Arbeitsgruppe darzustellen. Das ganze soll intern auf unserem Cluster laufen, damit man einfach auf Grafiken, Daten etc. zugreifen kann. Das Programm besteht aus zwei Teilen: Einem Navigator um die jeweiligen Datensätze auszuwählen und einem zweiten Bereich um die Daten darzustellen. Der Navigator ist ein Template, das ein Webformular erzeugt. Für die Darstellung der Daten gibt es verschiedene Templates, abhängig von den jeweiligen Daten.

Die beiden Templates (Navigator und Darstellung) habe ich einem weiterem Template gebündelt:

Code: Alles auswählen

<html>
%include navi_template **navi_keywords
%include data_template **data_keywords
</html>
``data_template`` ist der Name eines Strings, der von Python übergeben wird.


Edit: Ich wollte mich eigentlich nicht umbedingt zusätzlich mit Jinja2 beschäftigen. :wink:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

gkuhl hat geschrieben:Für die Darstellung der Daten gibt es verschiedene Templates, abhängig von den jeweiligen Daten.
Ja dann verlagere das Problem doch in Dein Script! Abhängig von den Daten renderst Du eben Template A, B oder C. Du bündelst die Templates eben nicht mehr in einem Proxy-template, sondern bindest bei jedem konkreten Daten-template den Navi-Bereich ein. Das sollte doch klappen?!?
Edit: Ich wollte mich eigentlich nicht umbedingt zusätzlich mit Jinja2 beschäftigen. :wink:
Ich kann's nur empfehlen :-) Ist ja nicht wirklich komplizierter als das von bottle - kann eben mehr. (Auch wenn ich hier eben ein Design-Problem sehe)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Kann mir jemand erklären, was ich falsch mache,
Du musst den _vollen_ Templatename inkl. Endung angeben. Also bei dir wahrscheinlich name.tpl :-)

Zur Datenübergabe: Das funktioniert auch. Wenn z.B. navi_keywords ein Dict ist und du

Code: Alles auswählen

%include name.tpl navi=navi_keywords
aufrufst, dann kannst du im Template name.tpl auf das Dict navi zugreifen, welches eine "Kopie" von navi_keywords ist.

Gruß, noisefloor
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Hyperion hat geschrieben:Ja dann verlagere das Problem doch in Dein Script! Abhängig von den Daten renderst Du eben Template A, B oder C. Du bündelst die Templates eben nicht mehr in einem Proxy-template, sondern bindest bei jedem konkreten Daten-template den Navi-Bereich ein. Das sollte doch klappen?!?
Danke, ich werde morgen mal schauen, ob ich das Problem stärker ins Skript binden kann.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

noisefloor hat geschrieben: Du musst den _vollen_ Templatename inkl. Endung angeben. Also bei dir wahrscheinlich name.tpl :-)
Nein will er ja grad nicht! Er will einen Platzhalter verwenden, in dem der Name des konkreten Templates steht, da dieser in inlcude eben dynamisch sein soll.

Was mir noch einfiele wäre eine Fallunterscheidung, sofern includes bei bottle in Bedingungsblöcken stehen dürfen. Damit könnte eine ID für ein konkretes Template übergeben:

Code: Alles auswählen

%if name == "foo":
    %include foo.tpl
%else:
    %include bar.tpl
%end
Aber letztlich sehe ich immer noch nicht den Vorteil, diese Logik in das Template zu verfrachten!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

%include unterstützt momentan nur statische Namen, keine Variablen. Als workaround kann ich dir _include() anbieten. Diese Funktion ist in allen Templates verfügbar und macht das gleiche wie %include, ist aber eine ganz normale Funktion.

Code: Alles auswählen

%name="template_name"
%_include(name, test="TEST")
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Defnull hat geschrieben:Als workaround kann ich dir _include() anbieten.
Danke, das funktioniert erstmal. Man muss aber zusätzlich noch "_stdout" angeben:

Code: Alles auswählen

%name="template_name"
%_include(name, _stdout=_stdout, test="TEST")
Grüße
Gerrit
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

gkuhl hat geschrieben:
Defnull hat geschrieben:Als workaround kann ich dir _include() anbieten.
Danke, das funktioniert erstmal. Man muss aber zusätzlich noch "_stdout" angeben.
Stimmt, das hab ich vergessen. Wäre sonst ja auch zu einfach gewesen ;)
Bottle: Micro Web Framework + Development Blog
Antworten