Hilfe mit exec bei Anpassung von Template Library stpy

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
Jackster
User
Beiträge: 2
Registriert: Dienstag 26. August 2008, 00:47

Hallo alle,

Ich benutze eine kleine template library Names [url=gttp://lucumr.pocoo.org/articles/simple-templates-in-python]stpy[/url] um HTML auszugeben.

Eine Kleinigkeit würde ich gerne anpassen:
Exisitiert eine im template verwendete Variable nicht, soll das Ganze nicht mit einem Attribute- bzw KeyError abgebrochen werden, stattdessen soll einfach "" (leerer string) ausgegeben werden, damit der Rest des Templates ordnungsgemäß dargestellt werden kann.

Leider stellt sich das nicht so einfach dar wie zuerst angenommen; der Quelltext von stpy findet sich hier http://dev.pocoo.org/hg/sandbox/diff/a4 ... py/stpy.py

Was ich versucht habe, ist das anpassen von render(), Zeile 110-160.

Mein erster Versuch war, das Werte-Dictionary wie folgt zu erweitern:

Code: Alles auswählen

 
class D(dict):
            def __getitem__(self, key):
                if not self.has_key(key):
                    self.update({key:''})    
                return super(D, self).__getitem__(key)
d = D(*args, **kwargs)
Damit wollte ich erzielen, dass wenn der Key nicht im Dictionary vorliegt, dass einfach ein leerer String zurückgegben wird, das ganze resultiert jedoch in einem
File "<template>", line 7, in <module>
TypeError: 'str' object is not callable
Mein zweiter Versuch war, die lokalen variablen des code objekts abzufragen, und falls diese nicht im Werte-Dictionary vertreten sind, auf '' zu setzen.

Code: Alles auswählen

 
for var in self.code.co_names:
    if var not in d:
          d[var] = ''
aber auch hier die gleiche Meldung:
File "<template>", line 7, in <module>
TypeError: 'str' object is not callable

Ich scheine also irgendwie das Konzept von exec (

Code: Alles auswählen

exec self.code in d
) nicht zu verstehen, und so langsam gehen mir auch die Ideen aus, das Problem zu lösen.

Ich wäre wirklich dankbar, wenn mir jemand weiterhelfen würde. Danke.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich wäre ja erfreut wenn du den Code verlinken würdest und nicht das Diff, aber was solls, hier mal etwas hässlich zusammengepatchtes. Normalerweise würde ich aber raten Jinja zu verwenden, dort kannst du auswählen wie es sich bei nicht existierenden Variablen verhalten soll.

Wenn man Lust hat, kann man das ganze noch mit einem DefaultDict implementieren, das geht natürlich auch.

Edit: Ein besserer Patch, mit ``defaultdict``. Also grob dem selben was du da versuchst, nur ohne das dict nochmal implementieren zu müssen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Jackster
User
Beiträge: 2
Registriert: Dienstag 26. August 2008, 00:47

Danke, die Idee mit dem defaultdict ist gut und funktioniert auch .. mit einer Ausnahme:

Hier etwas Testcode:

Code: Alles auswählen

templ = '''
<? if values: ?>
    I have <?= values ?>
<? end ?>

<? for value in values: ?>
    * <?= value ?>
<? end ?>

<? for i, value in enumerate(values): ?>
    *  <?= i ?> <?= value ?>
<? end ?>
'''
 
t = Template(templ)
print t.render(values = [1,2,3,4,5])
Das Problem stellt enumerate() dar:

Mit dem normalen dict läuft es wie erwartet durch, defaultdict wirft:
File "<template>", line 12, in <module>
TypeError: 'str' object is not callable
Eventuell bin ich schon an die Begrenzung dieser derart kleinen Lösung gestoßen, vielleicht gibt es aber auch eine einfache Lösung ... ?

Edit: Die Lösung des Problems ist, dass enumerate noch explizit in das exec-dict eingefügt werden muss,

Code: Alles auswählen

d['enumerate'] = enumerate
Dann geht es, wieso auch immer ...
Antworten