Python Jinja2 Array Bedingungfür Zeichen am ende

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
nieselfriem
User
Beiträge: 135
Registriert: Sonntag 13. Januar 2013, 16:00

Hallo,

ich möchte mit Python und einem Jinja2 Tempalte ein Latex-File erstellen. Dazu habe ich mir ein kleinen Prototypen erstellt, der ein Array besitzt und dies in eine sehr vereinfachte Latex-tabelle fassen soll. Das Thema ist nun für mich, wie verhindere ich, dass am ende des Tabellezeile das trennende &-Zeichen nicht gesetzt wird, sondern nur zwischen den "Elementen/Zellen?
Ich habe es mit einem Counter probiert an dem ich dann eine if Bedingung im Template setzen wollte. Leider wird dieser nicht bis 2 im Template gezählt sondern nur bis 1.

Code: Alles auswählen

import os
import jinja2
import time
import subprocess
import os

def render(tpl_path, context):
    path, filename = os.path.split(tpl_path)
    return jinja2.Environment(
        loader=jinja2.FileSystemLoader(path or './')
    ).get_template(filename).render(context)

arrays=[["Ring", "Pinkring12","1 Stück", "15"], ["Kette", "Tollekette","2 Stück", "25"], ["Collier", "Tolle Collier","3 Stück", "25"]]
context = {
'arrays': arrays
}

result = render('template.j2', context)
print(result)
[codebox=text file=template.j2]{% for array in arrays %} {% for elem in array -%} {% set counter = 0 -%} {% set counter = counter + 1 -%} {{ elem }} & {{ counter }} {% endfor -%} \\
{% endfor %}
[/code]

Das ist das Resultat aus dem obigen Skript und dem Template. Wie zu erkennen ist, wird der Counter nur um 1 erhöht statt auf 2 (drei Elemente je innerem Array). Und das eigentliche Problem ist dass ich das letzte &-Zeichen einer Zeilen nicht gesetzt haben möchte. Evtl gibt es einen besseren Weg, als das über irgendwelche Counter zu lösen.

Was raus kommt ( Vorgesetzte 1 wie bei 1 13 ergibt sich aus der Ausgabe von {{ counter }})
[codebox=text file=Ausgabe.txt]
Ring & 1 Pinkring12 & 1 1 Stück & 1 15 & 1 \\
Kette & 1 Tollekette & 1 2 Stück & 1 25 & 1 \\
Collier & 1 Tolle Collier & 1 3 Stück & 1 25 & 1 \\
[/code]

Was ich haben möchte:
[codebox=text file=Unbenannt.txt] Ring & Pinkring12 & 1 Stück & 15 \\
Kette & Tollekette & 2 Stück & 25 \\
Collier & Tolle Collier & 3 Stück & 25 \\[/code]

VG niesel
BlackJack

@nieselfriem: So einen `counter` musst Du Dir gar nicht selber basteln, den gibt es schon. Und auch schon praktische Attribute die verraten ob es beispielsweise das erste oder das letzte Element ist. Schau mal nach `loop` beziehungsweise `loop.last` in der Dokumentation von Jinja's ``for``.

Edit: Und wenn bei den einzelnen Elementen keine weitere Templatelogik mehr erforderlich ist, ginge eventuell auch einfach der `join`-Filter statt einer expliziten Schleife.
BlackJack

@nieselfriem: Dein `counter` funktioniert so ja überhaupt nicht, der zählt auch nicht wirklich denn Du setzt den auf 0 und dann *sofort* auf 0 + 1, und das für *jedes* innere Element. Die Stelle wo Du den Wert dann in die Ausgabe einfügst ist auch etwas schräg: nicht beim `elem`-Wert sondern nach dem Zellentrenner ``&`` vor das *nächste* `elem` oder das Tabellenzeilen-abschliessende ``\\``. Das ist verwirrend. Hier mal Dein Code so eingerückt das man besser sieht was da passiert:
[codebox=text file=Unbenannt.txt]{% for array in arrays %}
{% for elem in array -%}
{% set counter = 0 -%}
{% set counter = counter + 1 -%}
{{ elem }} &
{{ counter }}
{% endfor -%} \\
{% endfor %}[/code]

Du kannst entweder das `loop`-Objekt verwenden (ungetestet):
[codebox=text file=Unbenannt.txt]{% for array in arrays %}
{% for elem in array -%}
{{ elem }} {% if not loop.last %}&{% endif %}
{% endfor -%} \\
{% endfor %}[/code]

Oder den `join`-Filter (ungetestet):
[codebox=text file=Unbenannt.txt]{% for array in arrays %}
{{ array|join(' & ') }} \\
{% endfor %}[/code]
Benutzeravatar
nieselfriem
User
Beiträge: 135
Registriert: Sonntag 13. Januar 2013, 16:00

Hi,

viel Dank! Beide Varianten funktionieren einwandfrei.

VG niesel
Antworten