Fixed #23420 - broken warning for unbound naive datetime objects

Fixed issue with warning message displayed for unbound naive datetime
objects when USE_TZ is True. Adds unit test that demonstrates the issue
(discoverable when using a custom lookup in MySQL).
This commit is contained in:
Andy Chosak 2014-10-08 15:12:42 -04:00 committed by Anssi Kääriäinen
parent c548c8d0d1
commit ceb1ffcc8d
4 changed files with 48 additions and 5 deletions

View File

@ -1402,9 +1402,13 @@ class DateTimeField(DateField):
# For backwards compatibility, interpret naive datetimes in local # For backwards compatibility, interpret naive datetimes in local
# time. This won't work during DST change, but we can't do much # time. This won't work during DST change, but we can't do much
# about it, so we let the exceptions percolate up the call stack. # about it, so we let the exceptions percolate up the call stack.
warnings.warn("DateTimeField %s.%s received a naive datetime (%s)" try:
name = '%s.%s' % (self.model.__name__, self.name)
except AttributeError:
name = '(unbound)'
warnings.warn("DateTimeField %s received a naive datetime (%s)"
" while time zone support is active." % " while time zone support is active." %
(self.model.__name__, self.name, value), (name, value),
RuntimeWarning) RuntimeWarning)
default_timezone = timezone.get_default_timezone() default_timezone = timezone.get_default_timezone()
value = timezone.make_aware(value, default_timezone) value = timezone.make_aware(value, default_timezone)

View File

@ -43,3 +43,6 @@ Bugfixes
* Fixed a migrations crash when adding ``GeometryField``\s with ``blank=True`` * Fixed a migrations crash when adding ``GeometryField``\s with ``blank=True``
on PostGIS (:ticket:`23731`). on PostGIS (:ticket:`23731`).
* Allowed usage of ``DateTimeField()`` as ``Transform.output_field``
(:ticket:`23420`).

View File

@ -11,3 +11,11 @@ class Author(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
@python_2_unicode_compatible
class MySQLUnixTimestamp(models.Model):
timestamp = models.PositiveIntegerField()
def __str__(self):
return self.name

View File

@ -1,13 +1,14 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from datetime import date from datetime import date, datetime
import time
import unittest import unittest
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db import models from django.db import models
from django.db import connection from django.db import connection
from django.test import TestCase from django.test import TestCase, override_settings
from .models import Author from .models import Author, MySQLUnixTimestamp
class Div3Lookup(models.Lookup): class Div3Lookup(models.Lookup):
@ -172,6 +173,18 @@ class InMonth(models.lookups.Lookup):
(lhs, rhs, lhs, rhs), params) (lhs, rhs, lhs, rhs), params)
class DateTimeTransform(models.Transform):
lookup_name = 'as_datetime'
@property
def output_field(self):
return models.DateTimeField()
def as_sql(self, qn, connection):
lhs, params = qn.compile(self.lhs)
return 'from_unixtime({})'.format(lhs), params
class LookupTests(TestCase): class LookupTests(TestCase):
def test_basic_lookup(self): def test_basic_lookup(self):
a1 = Author.objects.create(name='a1', age=1) a1 = Author.objects.create(name='a1', age=1)
@ -353,6 +366,21 @@ class BilateralTransformTests(TestCase):
models.IntegerField._unregister_lookup(Mult3BilateralTransform) models.IntegerField._unregister_lookup(Mult3BilateralTransform)
@override_settings(USE_TZ=True)
class DateTimeLookupTests(TestCase):
@unittest.skipUnless(connection.vendor == 'mysql', "MySQL specific SQL used")
def test_datetime_output_field(self):
models.PositiveIntegerField.register_lookup(DateTimeTransform)
try:
ut = MySQLUnixTimestamp.objects.create(timestamp=time.time())
y2k = datetime(2000, 1, 1)
self.assertQuerysetEqual(
MySQLUnixTimestamp.objects.filter(timestamp__as_datetime__gt=y2k),
[ut], lambda x: x)
finally:
models.PositiveIntegerField._unregister_lookup(DateTimeTransform)
class YearLteTests(TestCase): class YearLteTests(TestCase):
def setUp(self): def setUp(self):
models.DateField.register_lookup(YearTransform) models.DateField.register_lookup(YearTransform)