Index: django/db/utils.py
===================================================================
--- django/db/utils.py	(revision 16922)
+++ django/db/utils.py	(working copy)
@@ -17,6 +17,16 @@
     pass
 
 
+def patch_exceptions(db_module):
+    """Patch a DB-API module's exceptions so that they derrive from
+    the backend independent Django exceptions."""
+    for django_exception in [DatabaseError, IntegrityError]:
+        db_exception = getattr(db_module, django_exception.__name__, None)
+        if not (db_exception is None or
+                issubclass(db_exception, django_exception)):
+            db_exception.__bases__ += (django_exception,)
+
+
 def load_backend(backend_name):
     # Look for a fully qualified database backend name
     try:
Index: django/db/backends/sqlite3/base.py
===================================================================
--- django/db/backends/sqlite3/base.py	(revision 16922)
+++ django/db/backends/sqlite3/base.py	(working copy)
@@ -30,6 +30,7 @@
 
 DatabaseError = Database.DatabaseError
 IntegrityError = Database.IntegrityError
+utils.patch_exceptions(Database)
 
 Database.register_converter("bool", lambda s: str(s) == '1')
 Database.register_converter("time", util.typecast_time)
@@ -267,21 +268,11 @@
     """
     def execute(self, query, params=()):
         query = self.convert_query(query)
-        try:
-            return Database.Cursor.execute(self, query, params)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
+        return Database.Cursor.execute(self, query, params)
 
     def executemany(self, query, param_list):
         query = self.convert_query(query)
-        try:
-            return Database.Cursor.executemany(self, query, param_list)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
+        return Database.Cursor.executemany(self, query, param_list)
 
     def convert_query(self, query):
         return FORMAT_QMARK_REGEX.sub('?', query).replace('%%','%')
Index: django/db/backends/mysql/base.py
===================================================================
--- django/db/backends/mysql/base.py	(revision 16922)
+++ django/db/backends/mysql/base.py	(working copy)
@@ -42,6 +42,7 @@
 
 DatabaseError = Database.DatabaseError
 IntegrityError = Database.IntegrityError
+utils.patch_exceptions(Database)
 
 # MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
 # timedelta in terms of actual behavior as they are signed and include days --
@@ -84,30 +85,22 @@
     def execute(self, query, args=None):
         try:
             return self.cursor.execute(query, args)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
         except Database.OperationalError, e:
             # Map some error codes to IntegrityError, since they seem to be
             # misclassified and Django would prefer the more logical place.
             if e[0] in self.codes_for_integrityerror:
-                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+                raise Database.IntegrityError, Database.IntegrityError(*tuple(e)), sys.exc_info()[2]
             raise
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
 
     def executemany(self, query, args):
         try:
             return self.cursor.executemany(query, args)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
         except Database.OperationalError, e:
             # Map some error codes to IntegrityError, since they seem to be
             # misclassified and Django would prefer the more logical place.
             if e[0] in self.codes_for_integrityerror:
-                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+                raise Database.IntegrityError, Database.IntegrityError(*tuple(e)), sys.exc_info()[2]
             raise
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
 
     def __getattr__(self, attr):
         if attr in self.__dict__:
Index: django/db/backends/postgresql_psycopg2/base.py
===================================================================
--- django/db/backends/postgresql_psycopg2/base.py	(revision 16922)
+++ django/db/backends/postgresql_psycopg2/base.py	(working copy)
@@ -29,43 +29,10 @@
 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
 psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
 psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)
+utils.patch_exceptions(Database)
 
 logger = getLogger('django.db.backends')
 
-class CursorWrapper(object):
-    """
-    A thin wrapper around psycopg2's normal cursor class so that we can catch
-    particular exception instances and reraise them with the right types.
-    """
-
-    def __init__(self, cursor):
-        self.cursor = cursor
-
-    def execute(self, query, args=None):
-        try:
-            return self.cursor.execute(query, args)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
-
-    def executemany(self, query, args):
-        try:
-            return self.cursor.executemany(query, args)
-        except Database.IntegrityError, e:
-            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
-        except Database.DatabaseError, e:
-            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
-
-    def __getattr__(self, attr):
-        if attr in self.__dict__:
-            return self.__dict__[attr]
-        else:
-            return getattr(self.cursor, attr)
-
-    def __iter__(self):
-        return iter(self.cursor)
-
 class DatabaseFeatures(BaseDatabaseFeatures):
     needs_datetime_string_cast = False
     can_return_id_from_insert = True
@@ -176,7 +143,7 @@
             if set_tz:
                 cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
             self._get_pg_version()
-        return CursorWrapper(cursor)
+        return cursor
 
     def _enter_transaction_management(self, managed):
         """
