bottle und ">" im template

Django, Flask, Bottle, WSGI, CGI…
Antworten
Dadapf
User
Beiträge: 28
Registriert: Mittwoch 16. Dezember 2009, 09:16

Guten Abend,

wie kann ich bottle dazu bringen, dass es mir "<" und ">" auch so an den Browser übergibt?
Wenn ich im template "<br></br>" stehen habe, wird es korrekt übergeben. Wenn ich jedoch eine Variable Text, mit Text = u'<br></br>', habe, die ins template mit {{Text}} eingebunden ist, so wird an den Browser "<br></br>" ausgeliefert.
Dank im Voraus,

Dadapf

p.s.: Merkwürdigerweise habe ich denselben Effekt, wenn ich "<br></br>" in ein separates template auslagere. Bei den anderen templates passiert es nicht.
Für heute ist Feierabend.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Erklärung findet sich in der Doku (wie so oft):
HTML special characters are escaped automatically to prevent XSS attacks. You can start the statement with an exclamation mark to disable escaping for that statement:

Code: Alles auswählen

>>> template('Hello {{name}}!', name='<b>World</b>')
u'Hello <b>World</b>!'
>>> template('Hello {{!name}}!', name='<b>World</b>')
u'Hello <b>World</b>!'
Wenn dich das sehr stört, dann solltest du vielleicht mal schauen, ob sich der XSS-Schutz irgendwo per Flag ausschalten lässt.
Dadapf
User
Beiträge: 28
Registriert: Mittwoch 16. Dezember 2009, 09:16

Guten Morgen,

die Dokumentation habe ich - auch gelesen; aber manchmal sucht man halt am falschen Ende ...
Vielen Dank für beise Hinweis. Ich habe es auch schon ausprobiert - und es funktioniert leider nicht.
Doch beide Versionen, snafus und meine, arbeiten wie gewünscht an einer anderen Stelle des Programmes. Der Unterschied ist eigentlich nur:

1. korrekte Übergabe bei

Code: Alles auswählen

Inhalt = Inhalt + u'<br></br>'
2. nicht korrekte Übergabe bei

Code: Alles auswählen

Inhalt = Inhalt + Funktion()
...
def Funktion():
  Text = u'bla'
  Text = Text +  u'<br></br>'
return Text
Das Problem ist wohl die Übergabe mit return; werde mal suchen gehen.

Dadapf
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich glaube nicht, das dein Code wirklich so aus sieht (return außerhalb der Funktion?). Poste doch vielleicht mal das Beispiel, das nicht funktioniert.
Bottle: Micro Web Framework + Development Blog
Dadapf
User
Beiträge: 28
Registriert: Mittwoch 16. Dezember 2009, 09:16

Ich habe meinen eigenen Quelltext nicht angeführt, sondern ein vereinfachtes Beispiel und dabei ist mir eine Einrückung abhanden gekommen. Entschuldigung. Korrekt sollte es natürlich

Code: Alles auswählen

Inhalt = Inhalt + Funktion()
...
def Funktion():
  Text = u'bla'
  Text = Text +  u'<br></br>'
  return Text
lauten.
Der eigentliche Quelltext ist nicht mehr gut strukturiert, da beim Ausprobieren gewachsen. Deswegen habe ich ihn nicht hineinstellen wollen. Die betreffenden Passagen - mit den relevanten Testzeilen in jeweils der Mitte der Funktionen - lauten:

Code: Alles auswählen

[...]
@get('/Seite_1')
def Ausgabe():
	def Zeilen_Kodekopf():
		Titel = u'Bilder aus den Bergen, Jahr 2010'
		Schluesselworte = u'Reisen, Hund, Saluki, Hunderucksack, Wandern, Berge'
		Browser_CSS = u'./Betriebsdateien/Assamir.css'
#		return template(u'Zeilen_Kodekopf', Text = (Titel, Schluesselworte, Browser_CSS))
		return template(u'Zeilen_Kodekopf', Text = (Daten [1], Daten [3], Browser_CSS))

	Inhalt = u''
	Inhalt = Zeilen_Doctype()
	Text = u'<br>uu</br>' 
	Inhalt = Inhalt + u'kk' + u'<br></br>' + u'kk' 
#	Inhalt = Inhalt + u'kk' + template(u'Zeilenumbruch') + u'kk' 
#	Inhalt = Inhalt + template(u'Zeilenumbruch_2', Textt = Text)
#	Inhalt = Inhalt + template(u'Hallo {{!Textt}}', Textt = Text)
	Inhalt = Inhalt + Zeilen_Kodekopf()
	Inhalt = Inhalt + Zeilen_Kopftext_Schaltflaechen_Unterseite()
	Inhalt = Inhalt + template(u'Zeilen_Bildergalerie_Anfang')
	Inhalt = Inhalt + Zeilen_Bilder()
	Inhalt = Inhalt + template(u'Zeilen_Bildergalerie_Ende')
# fehlt: Schaltflächenabdeckung
	return Inhalt
[...]
def Zeilen_Bilder():
	Inhalt = u''
	laufende_Nummer = 0
	Bildtext = u''
	Bildtext = Daten [16]
	for Index in (17, 18, 19, 20, 21, 22):
		if Daten [Index][0] != u'#':
#			Bildtext = Bildtext + u'<br></br>' + Daten [Index]
#			Bildtext = Bildtext + template(u'Zeilenumbruch') + Daten [Index]
			Text = u'<br>uu</br>' 
#			Bildtext = Bildtext + template(u'Zeilenumbruch_2', Textt = Text) + Daten [Index]
			Bildtext = Bildtext + template(u'Hallo {{!Textt}}', Textt = Text) + Daten [Index]
		else:
			break
#	Bildtext = Bildtext [9:]
	Inhalt = Inhalt + Zeilen_Bild(Daten [9], Daten [11], Daten [13], Daten [14], Bildtext, laufende_Nummer)
	return Inhalt
[...]
Nebenfrage: Lassen sich mit dem Forumseditor bei den Codebeispielen auch Zeilennummern hinzufügen?
Die beiden Test-template enthalten nur:
Zeilenumbruch:

Code: Alles auswählen

<br></br>
Zeilenumbruch_2:

Code: Alles auswählen

{{!Textt}}
In der Ausgabe-Funktion werden mir die "<" korrekt ausgegeben, in der Zeilen_Bilder-Funktion hingegen substituiert.
In der Liste Daten stehen nur Dateinamen und -pfade, sowie "normale" Prosa.

Dadapf
BlackJack

@Dadapf: Was macht denn `Zeilen_Bild()` mit `Bildtext`? Bist Du sicher, dass *da* die '<' nicht zu '<' werden?

Das sieht übrigens etwas schröcklich aus. Ziemlich umständlich und die Darstellung ist ja fast komplett in Python statt in den Templates geregelt.
Dadapf
User
Beiträge: 28
Registriert: Mittwoch 16. Dezember 2009, 09:16

ad BlackJack:
> Was macht denn `Zeilen_Bild()` mit `Bildtext`? Bist Du sicher, dass *da* die '<' nicht zu '<' werden?
Ich denke nein:

Code: Alles auswählen

def Zeilen_Bild(Bildformat, Bildname_gross, Bildname_klein, Bildersatztext, Bildtext, laufende_Nummer):
#def Zeilen_Bild(Daten [9], Daten [11], Daten [13], Daten [14], Daten [16], laufende_Nummer):
	Versatzindex = laufende_Nummer % 6 # Spaltenposition
	if Bildformat == u'h4zu3':
		Text = [Bildtyp [Versatzindex + 6]]
		Text.append(Bildname_gross)
		Text.append(Groessentyp [2])
		Text.append(Versatztyp [1])
		Text.append(Bildname_klein)
		Text.append(Groessentyp [3])
		Text.append(Bildersatztext)
		Text.append(Texttyp [Versatzindex + 6])
	elif Bildformat == u'q4zu3':
		Text = [Bildtyp [Versatzindex]]
		Text.append(Bildname_gross)
		Text.append(Groessentyp [0])
		Text.append(Versatztyp [0])
		Text.append(Bildname_klein)
		Text.append(Groessentyp [1])
		Text.append(Bildersatztext)
		Text.append(Texttyp [Versatzindex])
	else:
		print u'Fehler: ', Bildformat, u'q4zu3'; exit()
# Beim Bildtext die Umbrüche einfügen!
	Text.append(Bildtext)
	print Text
	Test = template(u'Zeilen_Bild', Text = Text)
	print Test
	return Test
#	return template(u'Zeilen_Bild', Text = Text)
mit template Zeilen_Bild

Code: Alles auswählen

			<li class="Bildfolge">
				<div class="Bild {{Text [0]}}">
					<img src="{{Text [1]}}" class="{{Text [2]}} {{Text [3]}}" alt=""></img>
					<img src="{{Text [4]}}" class="{{Text [5]}}" alt="Bild: {{Text [6]}}"></img>
				</div>
				<p class="{{Text [7]}}">{{Text [8]}}</p>
			</li>
> Das sieht übrigens etwas schröcklich aus. Ziemlich umständlich und die
> Darstellung ist ja fast komplett in Python statt in den Templates geregelt.
Wie geschrieben, sind es meine ersten Versuche. Weiter will ich eigentlich in den templates keinen Pythoncode stehen haben.

Dadapf
BlackJack

@Dadapf: Wo verhinderst Du denn im Template `Zeilen_Bild`, dass die '<'/'>' ersetzt werden? Ich sehe da kein einziges '!' bei den Ersetzungen.

In Templates gehört der nötige Code um die vorbereiteten Daten für die Darstellung zu formatieren. Auf der Anwendungsseite sollten wirklich nur die Daten bereitgestellt werden, ohne Code der die formatiert. Die Anwendung könnte zum Beispiel eine "zweidimensionale" Datenstruktur erstellen, die Objekte mit allen nötigen Daten für die jeweiligen Zellen in der Darstellung enthalten.

Diese Indexerei ist auch extrem unübersichtlich. Da blickst Du doch selbst nach einem Jahr nicht mehr durch welcher Index an welcher Stelle was genau bedeutet.

Desweiteren wird in der Funktion auf Daten zugefriffen, die nicht als Argumente übergeben werden und die aber auch nicht nach Konstanten aussehen. Das ist auch keine gute Idee.
Dadapf
User
Beiträge: 28
Registriert: Mittwoch 16. Dezember 2009, 09:16

Ich gebe mich geschlagen. Im template Zeilen_Bild hat vor dem "Text [8]" das Ausrufezeichen gefehlt. Daher hat es auch in den Testzeilen vorher nicht funktionieren können.
Die restliche Kritik nehme ich auch gerne an. Ich stehe da jedoch vor dem Problem, dass ich persönlich die Vermischung von Python und html in einer Datei sehr unübersichlich finde. Daher habe ich versucht, dieses zu trennen. Dass die Struktur dadurch nicht unbedingt einfacher wird, ist mir klar. Vielleicht komme ich im Laufe der Zeit auf eine elegantere Lösung.

> Desweiteren wird in der Funktion auf Daten zugefriffen, die nicht als Argumente übergeben
> werden und die aber auch nicht nach Konstanten aussehen. Das ist auch keine gute Idee.
? Die ...typen sind globale Tupel und enthalten CSS-Anweisungen bzw. deren Namen, beide sind "konstant".
Danke allen,

Dadapf
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

um es nochmal mit Code klar zu machen:

Code: Alles auswählen

#!/usr/bin/env python

from bottle import route, template, run

@route('/escape')
def escape():
    return template('escape.tpl',text='<h1>Hallo Welt</h1>')
    
@route('/no_escape')
def no_escape():
    return template('no_escape.tpl',text='<h1>Hallo Welt</h1>')
    
run()
'no_escape.tpl':

Code: Alles auswählen

{{!text}}
'escape.tpl':

Code: Alles auswählen

{{text}}
Gruß, noisefloor
Antworten