Jinja, Globals und Dictionary

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Jinja, Globals und Dictionary

Beitragvon Hyperion » Dienstag 17. Juni 2008, 23:38

Hallo,

mein Hirn ist zwar schon ein wenig heruntergefahren ob der Uhrzeit, aber ich stelle die Frage hier dann trotzdem noch.

Ich bin grad dabei eine kleine WSGI-Applikation mit Werkzeug und Jinja zu schreiben. Nun habe ich anscheinend aber ein Designproblem oder aber ein Verständnisproblem oder etwas anderes schlimmes ;-)

Also: Ich möchte eine URL zusammenbaslten und habe in einer utils.py Datei folgende Funktion:

Code: Alles auswählen

def url_for(endpoint, _external=False, **values):
    return local.url_adapter.build(endpoint, values, force_external=_external)

Diese ist identisch zu der aus dem Werkzeug-Tutorial und funktioniert aus meiner Applikation heraus auch.

Nun möchte ich auf meiner Hauptseite eine Liste von Links ausgeben, die zu Unterseiten führen, also der endpoint 'karte'. Der Aufbau der Links kann man aus der Definition der Regeln entnehmen:

Code: Alles auswählen

url_map=Map([
    Rule("/", endpoint="index"),
    Rule("/about", endpoint="about"),
    Rule("/karte<string:ident>", endpoint="karte"),
    Rule("/ziehung", endpoint="ziehung")
])

Also z.B. ergibt der Aufruf der Funktion url_for z.B. folgendes:

Code: Alles auswählen

/karte6

als Test bei mir so aufgerufen:

Code: Alles auswählen

print adapter.build("karte", dict(ident=6))

So weit so gut. Nun sollen die Links aber ja aus dem Template generiert werden. Dazu habe ich in Jinja eine Schleife, in der ich die url_for-Funktion aufrufen möchte. Dazu habe ich auch die Funktion in die globals von meiner Jinja-Instanz gepackt. zusätzlich die dict()-Funktion, da ich ja die Nummer mit übergeben muss. Hier erst mal der Jinja-Code:

Code: Alles auswählen

{% for karte in karten %}
    <li>
        <a href="{{ url_for('karte', dict(ident=5))|e }}">{{ karte.name|e }}</a>
    </li>
{% endfor %}

'karte' ist ja nun mein Alias für den Endpunkt und ident der zugehörige Parameter. Leider kommt letzterer nicht in der url_for()-Funktion an! Auf der Konsole bekomme ich folgendes:

Code: Alles auswählen

 ....
  File "/home/nelson/src/Python/karten/tarot/utils.py", line 15, in url_for
    return local.url_adapter.build(endpoint, values, force_external=_external)
  File "/usr/lib/python2.5/site-packages/Werkzeug-0.2-py2.5.egg/werkzeug/routing.py", line 1263, in build
    raise BuildError(endpoint, values, method)
BuildError: ('karte', {}, 'GET')

Logisch, da es keine Regel '/karte' gibt.

Nun also meine Frage: Kann ich kein Dictionary aus Jinja heraus als Parameter einer Funktion übergeben? (Wobei das in der Jinja-Doc nicht explizit erwähnt wird) Oder mache ich das schlicht falsch? Oder ist es grundsätzlich eine schlechte Idee, das aus Jinja heraus machen zu wollen?

Ich hoffe ich konnte das halbwegs klar darstellen und habe keine wichtige Angabe vergessen. Wenn doch liefere ich das gerne nach.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Beitragvon veers » Mittwoch 18. Juni 2008, 09:00

Versuch mal folgendes:

Code: Alles auswählen

url_for("karte", ident=6)

;)
My Website - 29a.ch
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Beitragvon Hyperion » Mittwoch 18. Juni 2008, 09:41

*patsch* Ja, wenn man nicht mehr fit im Hirn ist, sollte man das Coden einstellen ^^

Ich danke Dir!

Es tritt zwar in meiner Apache-Umgebung mit fastcgi nun ein build-Error auf, aber das versuche ich heute abend mal zu erforschen.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Mittwoch 18. Juni 2008, 15:07

Warum machst du nicht gleich ``url_for = local.url_adapter.build``? Ich binde so die Callable an mein Request-Objekt (was ein threadlocal-Objekt ist). So hast du dann im Template die gängige ``build``-Syntax: ``url_for('karte', {'ident': 6}, external=True)`` (oder eben ohne ``external``).
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Beitragvon Hyperion » Mittwoch 18. Juni 2008, 15:11

Ehrlich gesagt: Keine Ahnung ;-) Ich bin da noch nicht so tief drin und habe mich am Tutorial von Werkzeug orientiert. Evtl. wird das dort aus bestimmten Gründen so gemacht, die ich übersehen oder nicht kapiert haben könnte und die bei mir wirklich keine Rolle spielen.

Danke für den Tipp, das werde ich mir heute abend sicherlich mal angucken!

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder