[Django] Dateipfade als Url bereitstellen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Hallo,

ich hänge seit einiger Zeit an einem Problem ohne wirklich weiter zu kommen. Ich habe in meinem Heimnetzwerk einen Rechner als Server umfunktioniert. Auf dem Server liegen verschiedene Musikdateien. Dazu habe ich eine Django-Oberfläche gebastelt, um über eine Suchfunktion Lieder auszuwählen und gleich im Browser abzuspielen.
Das ganze läuft mit einem Apache und wsgi. In einer MySQL-Datenbank speichere ich nur die Dateipfade. Über die Suchfunktion werden mir die Dateipfade als Link im Browser ausgegeben. Das funktioniert auch wunderbar, so lange keine Umlaute o.ä. im Link enthalten sind.
Aus der Datenbank wird der Link als unicode geliefert. Ein sys.getfilesystemencoding() liefert mir ein ANSI_X3.4-1968 und sys.getdefaultencoding() liefert ascii.

Aber nur wenn ich im view folgendes encoding setze, bekomme ich keinen Fehler:

Code: Alles auswählen

if request.method == 'POST':
    form = SearchForm(request.POST)
    s_title = request.POST.get('f_title', '')
    s_artist = request.POST.get('f_artist', '')
    if s_title and s_artist:
        result = LiedDetails.objects.filter(titel__icontains=s_title, kuenstler__icontains=s_artist)
    for song in result:
        song.dateipfad = song.dateipfad.encode('iso-8859-1')
Lasse ich die Links im unicode-Format, werden die Links richtig im Browser angezeigt, funktionieren aber nicht (kommt beim Download ein coding-Fehler). Deshalb versuche ich schon im view das Encoding zu setzen.

Jetzt habe ich aber das Problem, dass nicht die richtige Url im Link angezeigt wird.
Hier ein Ausschnitt aus dem Template:

Code: Alles auswählen

{% for song in result %}
        <tr font-size="2">
            <td> {{ song.titel }} </td>
            <td> {{ song.kuenstler }} </td>
            <td align="center"> {{ song.laenge }} </td>
            <td align="center"> {{ song.bitrate }} </td>
            <td align="center"> {{ song.dateidatum }} </td>
            <td><a href={{ song.dateipfad|urlencode }}>Download</a></td>
        </tr>
Wie bekomme ich es hin, dass auch eine Url mit Umlauten richtig angezeigt wird und vor allem auch funktioniert?

Mawilo
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Gib deinem HTML-Dokument eine Charset-Information mit und liefere den HTML-Souce in diesem Encoding aus. Den Rest macht dein Browser für dich ;-)

Ansonsten wäre es interessant zu wissen, WELCHEN Fehler du erhältst.
Benutzeravatar
Mawilo
User
Beiträge: 452
Registriert: Sonntag 22. Februar 2004, 10:58
Wohnort: Sachsen
Kontaktdaten:

Ich habe in der html-Datei folgendes Charset angegeben:

Code: Alles auswählen

<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
Wenn ich im view nur die Werte aus der Datenbank weiterreiche, erhalte ich einen UnicodeEncodeError.

Gebe ich im view ein Encoding an:

Code: Alles auswählen

for song in result:
    song.dateipfad = song.dateipfad.encode('iso-8859-1')
wird bei Dateien mit Umlauten nicht die richtige Url dargestellt, sondern es wird die Url zum aktuellen html-Dokument angezeigt (die auch im Browser in der Url-Zeile steht).

Anscheinend wird die richtige Url im template durch urlencode herausgefiltert. Lasse ich aber das urlencode weg, werden bei den bisher funktionierenden Links ohne Umlaute keine Dateinamen mehr angezeigt (sondern nur die Pfade bis zum Verzeichnis).
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Das Problem ist vielschichtig. Es beginnt damit, dass es AFAIK keinen Standard gibt, wie URLs mit Unicode-Zeichen in Browsers kodiert werden. Ich meine, die meisten benutzen UTF-8. Fakt ist, dass URLs keine solchen Zeichen direkt enthalten dürfen. Ein "ä" kodiert sich dann als %C3%A4 und mit etwas Glück zeigt der Browser in der Adressleiste bzw. Statuszeile dann wieder ein "ä" an. Das nächste Problem ist, wie man die Umlaute korrekt auf einer Webseite anzeigt. Dazu wurde ja schon viel gesagt. Natürlich muss das HTML-Dokument das passende Encoding deklarieren und dann auch benutzen. Wenn man's nicht macht, gilt ISO-8859-1 und das hat man fast nie. Unter Windows arbeitet man meist mit CP1252 auf dem Mac mit "Mac OS Roman" aka MacRoman. Unter Linux hat man vielleicht ISO-8859-15, damit man auch ein €-Zeichen hat. UTF-8 ist ein guter gemeinsamer Nenner. Das wiederum betrifft aber nicht die URLs, sondern nur die restliche Webseite. Natürlich ist dann noch wichtig, wie Django die URL interpretiert. Ohne es ausprobiert zu haben, vermute ich, dass man sie manuell von UTF-8 zurück in Unicode verwandeln muss, um dann wieder ein "ä" zu erhalten und in der DB gibt es ein weiteres Mal ein Encoding. Ich vermute, dass die DB nicht "Unicode" liefert, weil das kein Encoding ist, sondern die Beschreibung für eine Zeichensammlung. Auch die DB muss die Zeichen in Bytes kodieren, z.B. mit UTF-8, UTF-16, UTF-32 oder ISO-8859-1. Was Python über "sys" meldet, ist total egal, denn das betrifft nur Dateien (und Print-Befehle) und da sollte man eigentlich immer explizit das Encoding angeben.

Stefan
Antworten