HTML-Dokument dynamisch erzeugt - leider ohne Bilder

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

HTML-Dokument dynamisch erzeugt - leider ohne Bilder

Beitragvon numerix » Dienstag 12. Februar 2008, 21:44

Nach vielem Experimentieren und einiger Zeit des Suchens habe ich es leider immer noch nicht geschafft ..

Das Problem:

Ich möchte eine HTML-Seite mit einem Python-Skript via CGI generieren.
Das klappt auch alles wie es soll. Leider werden aber die Bilder nicht mit angezeigt. Ja ja, das wird ein Pfad-Problem sein, aber ich sehe es nicht.

Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# /cgi-bin/test.py

import os

htmlpath = "../htdocs/htmlordner/"

print "Content-Type: text/html"
print
print os.listdir(htmlpath)

file = open(htmlpath+"test.html","r")
page = file.read()
file.close()
# page = page.replace('<img src="','<img src="'+htmlpath)   
print page



Die Ausgabe von os.listdir(htmlpath) zeigt mir, dass alle in test.html eingebundene Bilder auch tatsächlich im gleichen Verzeichnis sind wie die Datei html.test auch. Folglich habe ich sie in der html-Datei eingebunden mit <img src="bild1.jpg"> etc.
Auch der Quelltext der "erzeugten" html-Datei weist dies so aus.
Rufe ich die Datei test.html direkt auf, sind die Bilder korrekt enthalten.

Testweise habe ich die oben auskommentierte Zeile mal eingefügt,
dann enthält die erzeugte html-Seite von /cgi-bin aus gesehen den gleichen Pfad wie test.html, was der Quelltext der "erzeugten" html-Datei auch ausweist, aber es funktioniert immer noch nicht.

Testweise habe ich auch mal die Bilddateien nach /cgi-bin kopiert, aber
auch das brachte keinen Erfolg.

Klar gibt es verschiedene Möglichkeiten, etwa durch absolute Pfadangaben oder einen URL das Bild zu erreichen, aber das gefällt mir nicht, weil ich dann unterscheiden muss zwischen der lokal angelegten/entwickelten Website und der auf den Webserver hochgeladenen.
Gnushi
User
Beiträge: 77
Registriert: Dienstag 12. Dezember 2006, 09:49

Re: HTML-Dokument dynamisch erzeugt - leider ohne Bilder

Beitragvon Gnushi » Dienstag 12. Februar 2008, 22:12

Hi!
pütone hat geschrieben:Das klappt auch alles wie es soll. Leider werden aber die Bilder nicht mit angezeigt. Ja ja, das wird ein Pfad-Problem sein, aber ich sehe es nicht.


Kannst du mal den <IMG...> Ausschnitt Deiner HTML-Datei zeigen? Kann Dein Browser Bilder laden? Sind die Bilder laut Rechten lesbar für _alle_?

GnuShi
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Dienstag 12. Februar 2008, 23:10

Hier nochmal in aller Klarheit (hoffentlich):

Folgende Dateien

/website/cgi-bin/cgitest.py
/website/cgi-bin/python-powered-70x28.png
/website/htdocs/pytest/cgitest.html
/website/htdocs/pytest/python-powered-70x28.png

Bilddatei absichtlich an beiden Stellen; hilft aber nicht.
Rufe ich das HTML-Dokument direkt auf, ist die Grafik sichtbar. Rufe ich sie über das Python-Skript auf, ist sie nicht sichtbar und es erscheint der Alternativtext.

Inhalt von cgitest.html

<html>
<head>
<title>Python CGI-Test</title>
</head>
<body>
<p>Hier sollte die Grafik erscheinen:</p>
<p><img src="python-powered-70x28.png" width="70" height="28" alt="Grafik fehlt!" /></p>

<p>Hier <a href="../../cgi-bin/cgitest.py">wieder aufrufen mit CGI-Skript</a>.</p>
</body>
</html>


Inhalt von cgitest.py

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

file = open("../htdocs/pytest/cgitest.html","r")
page = file.read()
file.close()

print "Content-Type: text/html"
print
print page
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Dienstag 12. Februar 2008, 23:48

Der HTML-Output referenziert die Datei im selben Verzeichnis. Bei der statischen Variante klappt das auch wie gewohnt. Bei der CGI-Variante allerdings vermutlich deshalb nicht, weil aus /cgi-bin/ normalerweise keine statischen Dateien ausgeliefert werden, IIRC. Wenn du also `/cgi-bin/python-powered-70x28.png` nicht direkt im Browser aufrufen kannst, liegt es daran, und entsprechend wird die Grafik auch nicht in der dynamisch generierten Seite eingebunden.

Lösung: Verweise in der dynamisch generierten Seite auf einen (vorzugsweise absoluten) festen Pfad in deinem `htdocs`-Verzeichnis, in diesem Fall also `/pytest/python-powered-70x28.png`.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Mittwoch 13. Februar 2008, 11:04

Das Problem:
Ich möchte eine HTML-Seite mit einem Python-Skript via CGI generieren.


Ist das Problem wirklich, dass du eine HTML-Seite _via CGI_ machen willst, oder willst du eine dynamische HTML-Seite machen?
Wenn zweiteres: benutze besser WSGI, das kann man dann auch als CGI einbinden, es hat allerdings Vorteile, wie z.B. "middleware", sie man dazu nutzen kann, dass statischer inhalt mitgeliefert wird.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 13. Februar 2008, 11:57

Hallo pütone!

Wie bereits von Y0Gi festgestellt wurde: *htdocs* ist nach ausen hin der Root-Ordner. *cgi-bin* wird nur als *Alias* eingebunden.

Weiters rate ich dir, dass du dir einen eigenen Projektordner unterhalb von *htdocs* erstellst und nur in diesem Ordner arbeitest. So kannst du dein Projekt einfacher verwalten.

Unterhalb deines Projektordners kannst du einen eigenen *cgi-bin*-Ordner anlegen und die Berechtigungen dieses Ordners so setzen, dass die darin enthaltenen Dateien nicht ohne interpretieren ausgeliefert werden dürfen. Siehe dazu auch: http://halvar.at/python/xampp_python_cg ... einstellen

Du kannst so aber auch komplett ohne einen eigenen *cgi-bin*-Ordner arbeiten.

Du solltest Pfade mit ``os.path.join()`` zusammenfügen. Das ist plattformübergreifend und weniger fehleranfällig.

So etwas wie das hier

Code: Alles auswählen

file = open(htmlpath+"test.html","r")
page = file.read()
file.close()
# page = page.replace('<img src="','<img src="'+htmlpath)   
print page

ist doch wohl nicht dein Ernst, oder doch? Das lässt man von einer Vorlagensprache wie z.B. Cheetah erledigen. Und das funktioniert auch mit CGI wunderbar.
Leider ist dieser Erfahrungsbericht noch nicht ganz fertig, aber gewisse Grundzüge sollten daraus schon hervor gehen. Vielleicht kannst du damit etwas anfangen: http://halvar.at/python/cheetah_apache_cgi/

Cheetah musst du natürlich nicht in dein Webprojekt einbinden, wenn du Cheetah normal für Python installierst. Das Einbinden ist nur dann interessant, wenn du dein Webprojekt bei einem Provider hosten möchtest.

Der Vorteil bei diesem Verfahren ist, dass du dir Python-Module erstellen kannst, die du dann von deiner Cheetah-Vorlage aus importieren und verwenden kannst. Probiere es mal aus. Vielleicht ist das ja etwas für dich. ;-)

Für größere Webprojekte empfehle ich dir, auf ein WSGI-kompatibles Framework wie z.B. CherryPy umzusteigen und CGI zurück zu lassen. Denn CGI ist ziemlich weit unten. Du musst dich um viele Dinge, wie z.B. Session-Handling, selber kümmern. Solche Arbeiten nimmt dir ein Framework ab.

Aber für den Anfang -- zum Probieren -- ist CGI unschlagbar, da es so gut wie überall funktioniert und eigentlich auch sehr einfach aufgebaut ist.

Mit dem Skript, ganz unten auf der Seite [wiki]CGI,[/wiki]kannst du recht einfach herausfinden, welche Daten du vom CG-Interface übermittelt bekommst und welcher Ordner der Home-(Root-)Ordner ist. Unbedingt ausprobieren und bei Problemen verwenden.

mfg
Gerold
:-)

PS: Falls wieder einmal Unmut darüber aufkommen sollte: Natürlich gibt es auch noch andere Vorlagensprachen und Webframeworks. Aber ich kenne mich mit CherryPy und Cheetah aus. Deshalb schreibe ich auch nur darüber.
Zuletzt geändert von gerold am Mittwoch 13. Februar 2008, 17:00, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Mittwoch 13. Februar 2008, 16:36

Vielen Dank zunächst an euch drei Helfer für eure Tipps!

@YOGi
Die Idee mit den absoluten Pfaden hatte ich ja auch schon; ich hatte auch schon erläutert, was mir daran nicht gefällt. Wenn es aber anders nicht geht, werde ich es so machen (müssen).

@keppla
Wie gerold dann anschließend angemerkt hat: Für den Anfang ist CGI unschlagbar. Und bei mir ist es der Anfang. Dass CGI hinsichtlich Performance etc. die so ziemlich schlechteste Lösung ist, ist mir bewusst. Das macht im Moment aber nichts.
Auf deine Frage: Im Prinzip will ich beides. Konkret habe ich eine kleine GUI-Anwendung (mit Tk) mit zwei Fenstern, einer Leiste mit Radiobuttons und einem normalen Button erstellt; in das eine Fenster gibt man einen Text ein, klickt auf den Button, und im anderen Fenster erscheint ein modifizierter Text. Es ist ein reines Übungsobjekt ohne wirklich praktischen Nutzen.

Nun wollte ich diese GUI-Anwendung möglichst 1:1 als HTML-Formular umsetzen - nur so, um zu sehen, was und wie es geht. Beim ersten Aufruf wollte ich die Seite statisch erzeugen (klar, MUSS man nicht, aber sollte mal so sein), nach Texteingabe und Klick auf den Button sollte sich die Seite selbst wieder aufrufen, allerdings im zweiten (vorher leeren) Textfeld dann auch den modifizierten Text zeigen. Soweit so gut. Nun enthält diese eine HTML-Seite auch eingebundene Bilder und DIE machen die Schwierigkeiten.

@Gerold
Danke für die ausführlichen Hinweise. Das meiste ist mir klar (gewesen), z.T. bin ich aber durch meinen Webhoster eingeschränkt. So lange ich auf meinem Rechner auf dem Trocken arbeite, kann ich meinen Apache natürlich so konfigurieren, dass ich alles inkl. cgi-Skripten in einen Unterordner packe. Das täte ich auch gerne, weil ich es - der ich bisher nur mit statischem HTML gearbeitet habe, auch bei größeren Projekten - auch immer so gemacht habe. Mein Webhoster lässt aber cgi-Skripte nur zu, wenn sie im /cgi-bin Ordner stehen, und ich wollte meine lokale Umgebung möglichst so einrichten, wie mein echter Webspace auch (zwangsweise) eingerichtet ist.
[Frage am Rande: Kann ich mittels einer .htaccess-Datei die o.g. Vorgabe des Webserver-Betreibers aushebeln? Auf den Server selbst und seine Konfiguration habe ich nämlich keinen Zugriff. Wenn ich mit einer .htaccess-Datei, die mir z.B. die Ausführung von SSI ermöglicht (das funktioniert) auch cgi-Skripte aus anderen Verzeichnissen starten könnte, fände ich das auch besser. Ende der Frage am Rande.]

Weiter im Text: Vorlagensprachen, Frameworks usw. brauche ich nicht. Ich mache nur ein paar kleine Experimente! Ich will keine große Website mittels Python aufziehen. Jedenfalls noch nicht.

Die Daten, die mein CGI übermittelt, habe ich mit cgi.print_env() etc. schon abgefragt und gesichtet. Die absoluten Pfade der Grafikdateien könnte ich ermitteln. Hätte ich aber gerne vermieden - s.o.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 13. Februar 2008, 16:52

pütone hat geschrieben:[Frage am Rande: Kann ich mittels einer .htaccess-Datei die o.g. Vorgabe des Webserver-Betreibers aushebeln? Auf den Server selbst und seine Konfiguration habe ich nämlich keinen Zugriff. Wenn ich mit einer .htaccess-Datei, die mir z.B. die Ausführung von SSI ermöglicht (das funktioniert) auch cgi-Skripte aus anderen Verzeichnissen starten könnte, fände ich das auch besser. Ende der Frage am Rande.]

Ja. Nein. Hängt ab. Das hängt von der AllowOverride-Einstellung deines Webservers ab. Kannst es mal ausprobieren, es geht auch, aber dein Hoster kann das abgeschaltet haben.

pütone hat geschrieben:Weiter im Text: Vorlagensprachen, Frameworks usw. brauche ich nicht. Ich mache nur ein paar kleine Experimente! Ich will keine große Website mittels Python aufziehen. Jedenfalls noch nicht.

Templatesprachen wie Mako oder Jinja wären an dieser Stelle schon durchaus zu überlegen. Oder wenigstens die String-Template-Klassen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 13. Februar 2008, 17:12

pütone hat geschrieben:Vorlagensprachen, Frameworks usw. brauche ich nicht. Ich mache nur ein paar kleine Experimente!

Hallo pütone!

Vergiss es. Du brauchst mindestens eine Vorlagensprache. Ich zeige dir was der Vorteil so einer Vorlagensprache ist:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

from Cheetah.Template import Template

personen = ("Martin", "Bernhard", "Luggi", "Michael", "Franz")

html = """
<h2>$ueberschrift:</h2>
<ul>
  #for $person in $personen
    <li>$person</li>
  #end for
</ul>
"""

tmpl = Template(html)
tmpl.ueberschrift = "Teilnehmerliste"
tmpl.personen = personen

print str(tmpl)

Ergebnis:
[code=]<h2>Teilnehmerliste:</h2>
<ul>
<li>Martin</li>
<li>Bernhard</li>
<li>Luggi</li>
<li>Michael</li>
<li>Franz</li>
</ul>[/code]
mfg
Gerold
:-)

PS: Das funktioniert natürlich auch mit Unicode: http://paste.pocoo.org/show/27494/

.
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Mittwoch 13. Februar 2008, 17:46

@Gerold

Du scheinst ja wirklich ein großer Freund von Vorlagensprachen zu sein!

Für mich ist dein Beispiel der erste Kontakt mit einer solchen Vorlagensprache und es bestärkt mich gerade darin, sie für meine Bedürfnisse NICHT zu brauchen.

Ich hätte es so gemacht:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

personen = ("Martin", "Bernhard", "Luggi", "Michael", "Franz")

print "<h2>Teilnehmerliste:</h2>"
print "<ul>"
for person in personen:
    print "<li>"+person+"</li>"
print "</ul>"


Dafür brauche ich halb so viele Zeilen wie du und muss keine Vorlagensprache lernen.

Das soll kein grundsätzliches Plädoyer gegen Vorlagensprachen sein, aber für mich ist das (zur Zeit) nichts, was ich brauche.
(War natürlich trotzdem interessant, dein Beispiel anzusehen).

@Leonidas

Vielleicht kannst du mir in Sachen .htaccess ein bisschen Nachhilfe geben, denn der Apache ich für mich absolutes Neuland. In einem Ordner, aus dem heraus ich erfolgreich HTML-Dateien mit SSI aufrufen kann, befindet sich folgende .htaccess:

Code: Alles auswählen

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
Options +Includes


Ich habe folgende Zeilen ergänzt, um auch CGIs aus diesem Verzeichnis starten zu können, bin aber mehr als unsicher, ob das auch die richtigen Direktiven waren (sofern das überhaupt die richtige Vokabel an der Stelle ist):

Code: Alles auswählen

Options +ExecCGI
AddHandler cgi-skript


Das hat jedenfalls nicht funktioniert. Hätte ich es anders machen müssen?
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 13. Februar 2008, 17:59

Bezüglich CGI: bei AddHandler hast du keine Erweiterung angegeben. Schau dir das CGI-Howto an. Wenn du das gemacht hast und es dennoch nicht funktioniert, dann liegt das einfach daran, dass dein Hoster es eben deaktiviert hat.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Beitragvon BlackJack » Mittwoch 13. Februar 2008, 18:20

@pütone: Halb so viele Zeilen ist ein schwaches Argument weil dieses Verhältnis nur bei dem Minibeispiel stimmt.

Ich hätte es noch "komplizierter" gemacht als gerold und das Template in eine eigene Datei ausgelagert. Einer der grossen Vorteile HTML und Python in getrennten Dateien zu haben ist nämlich, dass man beides mit den geeigneten Werkzeugen bearbeiten kann. Dann kann man grafische Editoren für das HTML benutzen, oder wenigstens das HTML mit Syntax-Highlighting und Tag-Vervollständigung bearbeiten.

Früher oder später werden HTML-Fragmente im Quelltext unwartbar.

Dann gibt's das Problem, das man nicht einfach so alles 1:1 ausgeben kann ohne das HTML kaputt zu machen. Man muss zum Beispiel auf '<'-Zeichen achten.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Mittwoch 13. Februar 2008, 18:29

Du solltest dich nicht gegen die /cgi-bin/-Vorgaben wenden, die haben durchaus ihren Grund. Darin noch anderes als CGI-Scripts unterzubringen, ist $böse.

Wenn der Hoster es erlaubt, kannst du allerdings mittels mod_rewrite über die .htaccess den Pfad zum CGI-Script "hübscher" gestalten und es so aussehen lassen, als läge es als "foo.html" in deinem htdocs-Wurzelverzeichnis.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Mittwoch 13. Februar 2008, 18:47

@Leonidas & YOGi

Danke für die Hinweise. Ich werde beides ausprobieren, sobald ich Zeit finde.

@BlackJack
Nee, ist eben kein schwaches Argument, weil ich ja - worauf ich schon hingewiesen haben - auch nur ein kleines Beispiel habe, um das es geht. Ich bestreite ja gar nicht, dass es bei größeren Geschichten eine überaus sinnvolle und nette Sache ist, mit Templates zu arbeiten.

Einer der grossen Vorteile HTML und Python in getrennten Dateien zu haben ist nämlich, dass man beides mit den geeigneten Werkzeugen bearbeiten kann.


Da bin ich ganz deiner Meinung. Es ist auf jeden Fall keine schöne Sache, HTML-Quelltext in Python-Quelltexte einzubetten. Aber das ist bei Gerolds Beispiel auch mit Templates nicht anders. Aber ich vermute mal, dass das daran liegt, dass Gerold mich als Template-Greenhorn nicht überfordern wollte (das war auch gut so) und sich das dadurch ändern ließe:

Ich hätte es noch "komplizierter" gemacht als gerold und das Template in eine eigene Datei ausgelagert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Mittwoch 13. Februar 2008, 19:09

Hallo pütone!

Letzter Versuch! Danach gebe ich es auf. :lol:

Stichwort: Vorlagenvererbung!!!

Hauptvorlage "hauptvorlage.tmpl":
http://paste.pocoo.org/show/27521/

Seite 1 "seite1.tmpl":
http://paste.pocoo.org/show/27522/

Seite 1 gerendert "seite1.html":
http://paste.pocoo.org/show/27524/

Seite 2 "seite2.tmpl":
http://paste.pocoo.org/show/27523/

Seite 2 gerendert "seite2.html":
http://paste.pocoo.org/show/27525/

mfg
Gerold
:-)


PS: :mrgreen:

.
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder