1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

[1.7.x] Fixed #23365 -- Added support for timezone-aware datetimes to migrations.

Backport of a407b846b4 from master
This commit is contained in:
Rudy Mutter
2014-09-06 13:42:36 -07:00
committed by Loic Bistuer
parent d830665007
commit e31be40f16
5 changed files with 56 additions and 11 deletions

View File

@@ -5,7 +5,7 @@ import os
import sys
from django.apps import apps
from django.utils import datetime_safe, six
from django.utils import datetime_safe, six, timezone
from django.utils.six.moves import input
from .loader import MIGRATIONS_MODULE_NAME
@@ -108,7 +108,8 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
sys.exit(3)
else:
print("Please enter the default value now, as valid Python")
print("The datetime module is available, so you can do e.g. datetime.date.today()")
print("The datetime and django.utils.timezone modules are "
"available, so you can do e.g. timezone.now()")
while True:
if six.PY3:
# Six does not correctly abstract over the fact that
@@ -123,7 +124,7 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
sys.exit(1)
else:
try:
return eval(code, {}, {"datetime": datetime_safe})
return eval(code, {}, {"datetime": datetime_safe, "timezone": timezone})
except (SyntaxError, NameError) as e:
print("Invalid input: %s" % e)
return None

View File

@@ -16,6 +16,7 @@ from django.db.migrations.loader import MigrationLoader
from django.utils import datetime_safe, six
from django.utils.encoding import force_text
from django.utils.functional import Promise
from django.utils.timezone import utc
COMPILED_REGEX_TYPE = type(re.compile(''))
@@ -164,6 +165,20 @@ class MigrationWriter(object):
return (MIGRATION_TEMPLATE % items).encode("utf8")
@staticmethod
def serialize_datetime(value):
"""
Returns a serialized version of a datetime object that is valid,
executable python code. It converts timezone-aware values to utc with
an 'executable' utc representation of tzinfo.
"""
if value.tzinfo is not None and value.tzinfo != utc:
value = value.astimezone(utc)
value_repr = repr(value).replace("<UTC>", "utc")
if isinstance(value, datetime_safe.datetime):
value_repr = "datetime.%s" % value_repr
return value_repr
@property
def filename(self):
return "%s.py" % self.migration.name
@@ -267,12 +282,11 @@ class MigrationWriter(object):
return "{%s}" % (", ".join("%s: %s" % (k, v) for k, v in strings)), imports
# Datetimes
elif isinstance(value, datetime.datetime):
value_repr = cls.serialize_datetime(value)
imports = ["import datetime"]
if value.tzinfo is not None:
raise ValueError("Cannot serialize datetime values with timezones. Either use a callable value for default or remove the timezone.")
value_repr = repr(value)
if isinstance(value, datetime_safe.datetime):
value_repr = "datetime.%s" % value_repr
return value_repr, set(["import datetime"])
imports.append("from django.utils.timezone import utc")
return value_repr, set(imports)
# Dates
elif isinstance(value, datetime.date):
value_repr = repr(value)