From d0672a7344ea2eba53073f597f6adbed9023a279 Mon Sep 17 00:00:00 2001 From: James Bennett Date: Wed, 24 Jan 2007 19:57:41 +0000 Subject: [PATCH] 0.91-bufixes: Backport [4244] for those using legacy Django with psycopg1 git-svn-id: http://code.djangoproject.com/svn/django/branches/0.91-bugfixes@4419 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/db/backends/postgresql.py | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/django/core/db/backends/postgresql.py b/django/core/db/backends/postgresql.py index 0bc799c247..4032d76317 100644 --- a/django/core/db/backends/postgresql.py +++ b/django/core/db/backends/postgresql.py @@ -16,6 +16,38 @@ except ImportError: # Import copy of _thread_local.py from python 2.4 from django.utils._threading_local import local +def smart_basestring(s, charset): + if isinstance(s, unicode): + return s.encode(charset) + return s + +class UnicodeCursorWrapper(object): + """ + A thin wrapper around psycopg cursors that allows them to accept Unicode + strings as params. + + This is necessary because psycopg doesn't apply any DB quoting to + parameters that are Unicode strings. If a param is Unicode, this will + convert it to a bytestring using DEFAULT_CHARSET before passing it to + psycopg. + """ + def __init__(self, cursor, charset): + self.cursor = cursor + self.charset = charset + + def execute(self, sql, params=()): + return self.cursor.execute(sql, [smart_basestring(p, self.charset) for p in params]) + + def executemany(self, sql, param_list): + new_param_list = [tuple([smart_basestring(p, self.charset) for p in params]) for params in param_list] + return self.cursor.executemany(sql, new_param_list) + + def __getattr__(self, attr): + if self.__dict__.has_key(attr): + return self.__dict__[attr] + else: + return getattr(self.cursor, attr) + class DatabaseWrapper(local): def __init__(self): self.connection = None @@ -40,6 +72,7 @@ class DatabaseWrapper(local): self.connection.set_isolation_level(1) # make transactions transparent to all cursors cursor = self.connection.cursor() cursor.execute("SET TIME ZONE %s", [TIME_ZONE]) + cursor = UnicodeCursorWrapper(cursor, settings.DEFAULT_CHARSET) if DEBUG: return base.CursorDebugWrapper(cursor, self) return cursor