Code

Ticket #17728: 17728.diff

File 17728.diff, 5.5 KB (added by akaariai, 2 years ago)
Line 
1diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
2index 1455ba6..d215f4c 100644
3--- a/django/db/models/sql/where.py
4+++ b/django/db/models/sql/where.py
5@@ -8,7 +8,7 @@ import datetime
6 from itertools import repeat
7 
8 from django.utils import tree
9-from django.db.models.fields import Field
10+from django.db.models.fields import Field, DateTimeField
11 from django.db.models.sql.datastructures import EmptyResultSet, FullResultSet
12 
13 # Connection types
14@@ -145,6 +145,10 @@ class WhereNode(tree.Node):
15             except EmptyShortCircuit:
16                 raise EmptyResultSet
17         else:
18+            # If the value is a datetime value, we need to take care converting it into
19+            # proper db datettime type.
20+            if isinstance(params_or_value, datetime.datetime):
21+                params_or_value = connection.ops.value_to_db_datetime(params_or_value)
22             params = Field().get_db_prep_lookup(lookup_type, params_or_value,
23                 connection=connection, prepared=True)
24         if isinstance(lvalue, tuple):
25diff --git a/tests/modeltests/timezones/models.py b/tests/modeltests/timezones/models.py
26index 9296edf..f0cc792 100644
27--- a/tests/modeltests/timezones/models.py
28+++ b/tests/modeltests/timezones/models.py
29@@ -6,6 +6,13 @@ class Event(models.Model):
30 class MaybeEvent(models.Model):
31     dt = models.DateTimeField(blank=True, null=True)
32 
33+class Session(models.Model):
34+    name = models.CharField(max_length=20)
35+
36+class SessionEvent(models.Model):
37+    dt = models.DateTimeField()
38+    session = models.ForeignKey(Session, related_name='events')
39+
40 class Timestamp(models.Model):
41     created = models.DateTimeField(auto_now_add=True)
42     updated = models.DateTimeField(auto_now=True)
43diff --git a/tests/modeltests/timezones/tests.py b/tests/modeltests/timezones/tests.py
44index dc9cfb3..8184059 100644
45--- a/tests/modeltests/timezones/tests.py
46+++ b/tests/modeltests/timezones/tests.py
47@@ -25,7 +25,7 @@ from django.utils.tzinfo import FixedOffset
48 from django.utils.unittest import skipIf, skipUnless
49 
50 from .forms import EventForm, EventSplitForm, EventModelForm
51-from .models import Event, MaybeEvent, Timestamp
52+from .models import Event, MaybeEvent, Session, SessionEvent, Timestamp
53 
54 
55 # These tests use the EAT (Eastern Africa Time) and ICT (Indochina Time)
56@@ -231,6 +231,28 @@ class LegacyDatabaseTests(BaseDateTimeTests):
57             'dt__max': datetime.datetime(2011, 9, 1, 23, 20, 20),
58         })
59 
60+    def test_query_annotation(self):
61+        # Only min and max make sense for datetimes.
62+        morning = Session.objects.create(name='morning')
63+        afternoon = Session.objects.create(name='afternoon')
64+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20), session=afternoon)
65+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30), session=afternoon)
66+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40), session=morning)
67+        morning_min_dt = datetime.datetime(2011, 9, 1, 3, 20, 40)
68+        afternoon_min_dt = datetime.datetime(2011, 9, 1, 13, 20, 30)
69+        self.assertQuerysetEqual(
70+                Session.objects.annotate(dt=Min('events__dt')).order_by('dt'),
71+                [morning_min_dt, afternoon_min_dt],
72+                transform=lambda d: d.dt)
73+        self.assertQuerysetEqual(
74+                Session.objects.annotate(dt=Min('events__dt')).filter(dt__lt=afternoon_min_dt),
75+                [morning_min_dt],
76+                transform=lambda d: d.dt)
77+        self.assertQuerysetEqual(
78+                Session.objects.annotate(dt=Min('events__dt')).filter(dt__gte=afternoon_min_dt),
79+                [afternoon_min_dt],
80+                transform=lambda d: d.dt)
81+
82     def test_query_dates(self):
83         Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0))
84         Event.objects.create(dt=datetime.datetime(2011, 1, 1, 4, 30, 0))
85@@ -412,6 +434,28 @@ class NewDatabaseTests(BaseDateTimeTests):
86             'dt__max': datetime.datetime(2011, 9, 1, 23, 20, 20, tzinfo=EAT),
87         })
88 
89+    def test_query_annotation(self):
90+        # Only min and max make sense for datetimes.
91+        morning = Session.objects.create(name='morning')
92+        afternoon = Session.objects.create(name='afternoon')
93+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 23, 20, 20, tzinfo=EAT), session=afternoon)
94+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), session=afternoon)
95+        SessionEvent.objects.create(dt=datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT), session=morning)
96+        morning_min_dt = datetime.datetime(2011, 9, 1, 3, 20, 40, tzinfo=EAT)
97+        afternoon_min_dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
98+        self.assertQuerysetEqual(
99+                Session.objects.annotate(dt=Min('events__dt')).order_by('dt'),
100+                [morning_min_dt, afternoon_min_dt],
101+                transform=lambda d: d.dt)
102+        self.assertQuerysetEqual(
103+                Session.objects.annotate(dt=Min('events__dt')).filter(dt__lt=afternoon_min_dt),
104+                [morning_min_dt],
105+                transform=lambda d: d.dt)
106+        self.assertQuerysetEqual(
107+                Session.objects.annotate(dt=Min('events__dt')).filter(dt__gte=afternoon_min_dt),
108+                [afternoon_min_dt],
109+                transform=lambda d: d.dt)
110+
111     def test_query_dates(self):
112         # Same comment as in test_query_date_related_filters.
113         Event.objects.create(dt=datetime.datetime(2011, 1, 1, 1, 30, 0, tzinfo=EAT))