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:
committed by
Loic Bistuer
parent
d830665007
commit
e31be40f16
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user