Django: You must not use 8-bit bytestrings...

Django, Flask, Bottle, WSGI, CGI…
Antworten
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

Hallo,

ich habe ein Problem in Django. Ich habe ein Script geschrieben welches mir in Django Daten aus SQL Tabellen in Models einträgt. Das Script funktionierte bisher gut, nun habe ich es um eine Tabelle/Model erweitert. Beim speichern des Models bekomme ich nun eine eigenartige Fehlermeldung mit der ich nichts anfangen kann. Ich habe danach gegooglet. Man findet ein paar Treffer aber nichts wirklich hilfreiches. Da der Fehler beim speichern des Models auftritt vermute ich dass es an Django da das speichern ein Bestandteil davon ist.
Wer kennt die Fehlermeldung oder kann damit was anfangen und möchte mir helfen? Bin um jede Hilfe dankbar! Hier nun die Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "dbsync.py", line 1024, in <module>
    init_mmv()
  File "dbsync.py", line 978, in init_mmv
    add_rows(d)
  File "dbsync.py", line 906, in add_rows
    e.save()
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py", line 460, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py", line 553, in save_base
    result = manager._insert(values, return_id=update_pk, using=using)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/manager.py", line 195, in _insert
    return insert_query(self.model, values, **kwargs)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 1436, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 791, in execute_sql
    cursor = super(SQLInsertCompiler, self).execute_sql(None)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/sqlite3/base.py", line 234, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.DatabaseError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das übliche Problem mit Byte- vs. Unicode-Strings. Zum Verständnis der Thematik verweise ich auf meine Signatur :-)

Vermutlich arbeitest Du an einer Stelle intern nicht mit Unicode, sondern benutzt Bytestrings. Schau Dir halt mal die betreffende Stelle im Code an. Irgend wo hast Du da unsauber gearbeitet.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

Hallo,

habe mir eine funktion geschrieben, die den Fehler behebt. Die funktion lasse ich einfach auf jedes Feld im Model laufen, dass ich in die Datenbank einfügen will. Schon kommt keine Fehlermeldung mehr.. mfg ready

Code: Alles auswählen

def fixunicodes(txt):
  if type(txt) is not str:
    return txt
  
  replace = {"\xf6": "ö",
             "\xd6": "Ö",
             "\xe4": "ä",
             "\xc4": "Ä",
             "\xfc": "ü",
             "\xdc": "Ü",
             "\xdf": "ß",
             "\xb0": "°",
             "\xb2": "²" }
  
  for k in replace.keys():
    txt = string.replace(txt,k,replace[k])
    
  return txt
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das ist keine gute Lösung.

Lies dir mal http://wiki.python-forum.de/Von%20Umlau ... 0Encodings durch!

Wo kommen deine Daten die du in der DB Eintragen willst her? Du mußt sie einfach nach unicode wandeln und gut.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

jens hat geschrieben:Das ist keine gute Lösung.

Lies dir mal http://wiki.python-forum.de/Von%20Umlau ... 0Encodings durch!
Habe ich schon 2 mal gelesen. Alles versucht was darin steht. Die funktionen .encode und .decode gibt es bei mir überhauptnicht. Was es gibt ist die funktion unicode(). Damit habe ich versucht die bytestrings umzuwandeln. Leider vergebens. Ein utf-8 encoding verwende ich bereits.
jens hat geschrieben:Wo kommen deine Daten die du in der DB Eintragen willst her? Du mußt sie einfach nach unicode wandeln und gut.
Kommt aus einer Postgres Datenbank.. die verwendet afaik ISO-8859-15 als encoding. Einfach umwandeln (mit unicode()) hilft nicht.

mfg ready
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Greifst du auf die DB per Django ORM zu? Dann solltest du IMHO unicode bekommen. Ansonsten stimmt da was nicht.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

jens hat geschrieben:Greifst du auf die DB per Django ORM zu?
Nein, sondern per psycopg2.
mfg ready
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Jo, dann hast du das Problem schon mal eingekreist... Vielleicht baust du die Verbindung nicht richtig auf. Ich kenne mich allerdings mit Postgres nicht aus. Bei MySQLdb gibt es allerdings ein paar parameter die man setzten muß, damit man unicode erhält.

z.B. hab ich eben in https://code.djangoproject.com/browser/ ... g2/base.py das gefunden:

Code: Alles auswählen

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
...
self.connection.set_client_encoding('UTF8')
Btw. warum nutzt du das ORM nicht?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

ready hat geschrieben:
jens hat geschrieben:Das ist keine gute Lösung.

Lies dir mal http://wiki.python-forum.de/Von%20Umlau ... 0Encodings durch!
Habe ich schon 2 mal gelesen. Alles versucht was darin steht. Die funktionen .encode und .decode gibt es bei mir überhauptnicht. Was es gibt ist die funktion unicode(). Damit habe ich versucht die bytestrings umzuwandeln. Leider vergebens.
Das sind auch Methoden von String-Objekten - das hättest Du beim Durcharbeiten des Links schon kapieren können... ich verweise auch gerne noch mal auf meine Signatur :D

Vermutlich befindet sich die Ursache tatsächlich bei der Verbindung zur Datenbank. Da kannst Du sicher das Encoding des in der DB verwendeten Encodings einstellen, damit der ORM von Django die korrekte Wandlung in Unicode durchführen kann.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

jens hat geschrieben:Jo, dann hast du das Problem schon mal eingekreist... Vielleicht baust du die Verbindung nicht richtig auf. Ich kenne mich allerdings mit Postgres nicht aus. Bei MySQLdb gibt es allerdings ein paar parameter die man setzten muß, damit man unicode erhält.

z.B. hab ich eben in https://code.djangoproject.com/browser/ ... g2/base.py das gefunden:

Code: Alles auswählen

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
...
self.connection.set_client_encoding('UTF8')
Super, mit den Funktionen geht es jetzt auch ohne die o.g. fixunicodes Funktion.
jens hat geschrieben:Btw. warum nutzt du das ORM nicht?
Weil die Tabellen, die ich da auslese ja auch nicht mit dem ORM erzeugt wurden, sondern schon in Postgres existieren. Außerdem gab es damals glaub ich noch nicht die Möglichkeit in django mehrere Datenbanken zu verwenden. Jedenfalls bot sich das damals einfach nicht an =)

mfg ready
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

Hyperion hat geschrieben: Das sind auch Methoden von String-Objekten
Das hab ich schon geschnallt. Nur meine String Objekte scheinen diese Methode nicht zu haben. Verwende Python 2.6.
mfg ready
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

ready hat geschrieben:
Hyperion hat geschrieben: Das sind auch Methoden von String-Objekten
Das hab ich schon geschnallt. Nur meine String Objekte scheinen diese Methode nicht zu haben. Verwende Python 2.6.
mfg ready
Das kann nicht sein! Entweder sind es keine Strings oder aber Du interpretierst das "nicht haben" falsch.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

ready hat geschrieben:
jens hat geschrieben:Btw. warum nutzt du das ORM nicht?
Weil die Tabellen, die ich da auslese ja auch nicht mit dem ORM erzeugt wurden, sondern schon in Postgres existieren. Außerdem gab es damals glaub ich noch nicht die Möglichkeit in django mehrere Datenbanken zu verwenden. Jedenfalls bot sich das damals einfach nicht an =)
Du kennst aber inspectdb oder? -> https://docs.djangoproject.com/en/1.3/r ... #inspectdb

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ready
User
Beiträge: 33
Registriert: Sonntag 15. Juni 2008, 12:21
Kontaktdaten:

jens hat geschrieben:Du kennst aber inspectdb oder? -> https://docs.djangoproject.com/en/1.3/r ... #inspectdb
Kannte ich noch nicht, danke für den Hinweis.
Antworten