From 1418da7ee417dfc85cb2ebd034b95d21fe2ea015 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 16 Nov 2008 08:50:06 +0000 Subject: [PATCH] Fixed #6052 -- Worked around a bug in MySQLdb with regards to handling SafeUnicode (handle SafeString similarly, just to be safe). Based on a patch from sfllaw. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9467 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/backends/mysql/base.py | 20 +++++++++++--------- tests/modeltests/field_defaults/models.py | 7 ++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index bda4f8f596..2fb1988f7a 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -29,6 +29,7 @@ from django.db.backends.mysql.client import DatabaseClient from django.db.backends.mysql.creation import DatabaseCreation from django.db.backends.mysql.introspection import DatabaseIntrospection from django.db.backends.mysql.validation import DatabaseValidation +from django.utils.safestring import SafeString, SafeUnicode # Raise exceptions for database warnings if DEBUG is on from django.conf import settings @@ -39,12 +40,11 @@ if settings.DEBUG: DatabaseError = Database.DatabaseError IntegrityError = Database.IntegrityError -# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime -# module for time-related columns; older versions could have used mx.DateTime -# or strings if there were no datetime module. However, MySQLdb still returns -# TIME columns as timedelta -- they are more like timedelta in terms of actual -# behavior as they are signed and include days -- and Django expects time, so -# we still need to override that. +# 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 -- +# and Django expects time, so we still need to override that. We also need to +# add special handling for SafeUnicode and SafeString as MySQLdb's type +# checking is too tight to catch those (see Django ticket #6052). django_conversions = conversions.copy() django_conversions.update({ FIELD_TYPE.TIME: util.typecast_time, @@ -174,7 +174,7 @@ class DatabaseOperations(BaseDatabaseOperations): def value_to_db_datetime(self, value): if value is None: return None - + # MySQL doesn't support tz-aware datetimes if value.tzinfo is not None: raise ValueError("MySQL backend does not support timezone-aware datetimes.") @@ -185,11 +185,11 @@ class DatabaseOperations(BaseDatabaseOperations): def value_to_db_time(self, value): if value is None: return None - + # MySQL doesn't support tz-aware datetimes if value.tzinfo is not None: raise ValueError("MySQL backend does not support timezone-aware datetimes.") - + # MySQL doesn't support microseconds return unicode(value.replace(microsecond=0)) @@ -260,6 +260,8 @@ class DatabaseWrapper(BaseDatabaseWrapper): kwargs['port'] = int(settings.DATABASE_PORT) kwargs.update(self.options) self.connection = Database.connect(**kwargs) + self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode] + self.connection.encoders[SafeString] = self.connection.encoders[str] cursor = CursorWrapper(self.connection.cursor()) return cursor diff --git a/tests/modeltests/field_defaults/models.py b/tests/modeltests/field_defaults/models.py index 18afb72a93..f258134147 100644 --- a/tests/modeltests/field_defaults/models.py +++ b/tests/modeltests/field_defaults/models.py @@ -1,3 +1,4 @@ +# coding: utf-8 """ 32. Callable defaults @@ -19,7 +20,7 @@ class Article(models.Model): def __unicode__(self): return self.headline -__test__ = {'API_TESTS':""" +__test__ = {'API_TESTS': u""" >>> from datetime import datetime # No articles are in the system yet. @@ -51,8 +52,8 @@ True # make sure that SafeString/SafeUnicode fields work >>> from django.utils.safestring import SafeUnicode, SafeString ->>> a.headline = SafeUnicode(u'SafeUnicode Headline') +>>> a.headline = SafeUnicode(u'Iñtërnâtiônàlizætiøn1') >>> a.save() ->>> a.headline = SafeString(u'SafeString Headline') +>>> a.headline = SafeString(u'Iñtërnâtiônàlizætiøn1'.encode('utf-8')) >>> a.save() """}