Refs #19738 -- Removed timezone conversion in SQL queries executed outside of the ORM.

Per deprecation timeline.
This commit is contained in:
Tim Graham 2016-12-30 18:04:09 -05:00
parent b2ffbb00a5
commit e707e4c709
4 changed files with 8 additions and 49 deletions

View File

@ -6,18 +6,14 @@ MySQLdb is supported for Python 2 only: http://sourceforge.net/projects/mysql-py
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime
import re import re
import sys import sys
import warnings
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import utils from django.db import utils
from django.db.backends import utils as backend_utils from django.db.backends import utils as backend_utils
from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.base.base import BaseDatabaseWrapper
from django.utils import six, timezone from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.safestring import SafeBytes, SafeText from django.utils.safestring import SafeBytes, SafeText
@ -31,7 +27,7 @@ except ImportError as e:
) )
from MySQLdb.constants import CLIENT, FIELD_TYPE # isort:skip from MySQLdb.constants import CLIENT, FIELD_TYPE # isort:skip
from MySQLdb.converters import Thing2Literal, conversions # isort:skip from MySQLdb.converters import conversions # isort:skip
# Some of these import MySQLdb, so import them after checking if it's installed. # Some of these import MySQLdb, so import them after checking if it's installed.
from .client import DatabaseClient # isort:skip from .client import DatabaseClient # isort:skip
@ -51,20 +47,6 @@ if (version < (1, 2, 1) or (
raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__) raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__)
def adapt_datetime_warn_on_aware_datetime(value, conv):
# Remove this function and rely on the default adapter in Django 2.0.
if settings.USE_TZ and timezone.is_aware(value):
warnings.warn(
"The MySQL database adapter received an aware datetime (%s), "
"probably from cursor.execute(). Update your code to pass a "
"naive datetime in the database connection's time zone (UTC by "
"default).", RemovedInDjango20Warning)
# This doesn't account for the database connection's timezone,
# which isn't known. (That's why this adapter is deprecated.)
value = value.astimezone(timezone.utc).replace(tzinfo=None)
return Thing2Literal(value.strftime("%Y-%m-%d %H:%M:%S.%f"), conv)
# MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like # 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 -- # 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 # and Django expects time, so we still need to override that. We also need to
@ -75,7 +57,6 @@ django_conversions.update({
FIELD_TYPE.TIME: backend_utils.typecast_time, FIELD_TYPE.TIME: backend_utils.typecast_time,
FIELD_TYPE.DECIMAL: backend_utils.typecast_decimal, FIELD_TYPE.DECIMAL: backend_utils.typecast_decimal,
FIELD_TYPE.NEWDECIMAL: backend_utils.typecast_decimal, FIELD_TYPE.NEWDECIMAL: backend_utils.typecast_decimal,
datetime.datetime: adapt_datetime_warn_on_aware_datetime,
}) })
# This should match the numerical portion of the version numbers (we can treat # This should match the numerical portion of the version numbers (we can treat

View File

@ -10,14 +10,12 @@ import decimal
import os import os
import platform import platform
import sys import sys
import warnings
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import utils from django.db import utils
from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.base.base import BaseDatabaseWrapper
from django.utils import six, timezone from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_bytes, force_text from django.utils.encoding import force_bytes, force_text
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -326,13 +324,6 @@ class OracleParam(object):
# without being converted by DateTimeField.get_db_prep_value. # without being converted by DateTimeField.get_db_prep_value.
if settings.USE_TZ and (isinstance(param, datetime.datetime) and if settings.USE_TZ and (isinstance(param, datetime.datetime) and
not isinstance(param, Oracle_datetime)): not isinstance(param, Oracle_datetime)):
if timezone.is_aware(param):
warnings.warn(
"The Oracle database adapter received an aware datetime (%s), "
"probably from cursor.execute(). Update your code to pass a "
"naive datetime in the database connection's time zone (UTC by "
"default).", RemovedInDjango20Warning)
param = param.astimezone(timezone.utc).replace(tzinfo=None)
param = Oracle_datetime.from_datetime(param) param = Oracle_datetime.from_datetime(param)
string_size = 0 string_size = 0

View File

@ -6,14 +6,12 @@ standard library.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime
import decimal import decimal
import re import re
import warnings import warnings
import pytz import pytz
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import utils from django.db import utils
from django.db.backends import utils as backend_utils from django.db.backends import utils as backend_utils
@ -22,7 +20,6 @@ from django.utils import six, timezone
from django.utils.dateparse import ( from django.utils.dateparse import (
parse_date, parse_datetime, parse_duration, parse_time, parse_date, parse_datetime, parse_duration, parse_time,
) )
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.safestring import SafeBytes from django.utils.safestring import SafeBytes
@ -43,20 +40,6 @@ from .operations import DatabaseOperations # isort:skip
from .schema import DatabaseSchemaEditor # isort:skip from .schema import DatabaseSchemaEditor # isort:skip
def adapt_datetime_warn_on_aware_datetime(value):
# Remove this function and rely on the default adapter in Django 2.0.
if settings.USE_TZ and timezone.is_aware(value):
warnings.warn(
"The SQLite database adapter received an aware datetime (%s), "
"probably from cursor.execute(). Update your code to pass a "
"naive datetime in the database connection's time zone (UTC by "
"default).", RemovedInDjango20Warning)
# This doesn't account for the database connection's timezone,
# which isn't known. (That's why this adapter is deprecated.)
value = value.astimezone(timezone.utc).replace(tzinfo=None)
return value.isoformat(str(" "))
def decoder(conv_func): def decoder(conv_func):
""" The Python sqlite3 interface returns always byte strings. """ The Python sqlite3 interface returns always byte strings.
This function converts the received value to a regular string before This function converts the received value to a regular string before
@ -73,7 +56,6 @@ Database.register_converter(str("timestamp"), decoder(parse_datetime))
Database.register_converter(str("TIMESTAMP"), decoder(parse_datetime)) Database.register_converter(str("TIMESTAMP"), decoder(parse_datetime))
Database.register_converter(str("decimal"), decoder(backend_utils.typecast_decimal)) Database.register_converter(str("decimal"), decoder(backend_utils.typecast_decimal))
Database.register_adapter(datetime.datetime, adapt_datetime_warn_on_aware_datetime)
Database.register_adapter(decimal.Decimal, backend_utils.rev_typecast_decimal) Database.register_adapter(decimal.Decimal, backend_utils.rev_typecast_decimal)
if six.PY2: if six.PY2:
Database.register_adapter(str, lambda s: s.decode('utf-8')) Database.register_adapter(str, lambda s: s.decode('utf-8'))

View File

@ -254,3 +254,8 @@ these features.
required. required.
* ``django.db.models.fields.add_lazy_relation()`` is removed. * ``django.db.models.fields.add_lazy_relation()`` is removed.
* When time zone support is enabled, database backends that don't support time
zones no longer convert aware datetimes to naive values in UTC anymore when
such values are passed as parameters to SQL queries executed outside of the
ORM, e.g. with ``cursor.execute()``.