Commits

Waldemar Kornewald committed d139ec5

Added support for __year lookup type. Thanks a lot to Matt Bierner for the patch!

  • Participants
  • Parent commits 1efe3cb

Comments (0)

Files changed (5)

+import datetime
 from .creation import DatabaseCreation
 from ..utils import appid, have_appserver, on_production_server
 from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations, \
         # TODO: Only COUNT(*) should be supported. Raise NotImplementedError
         pass
 
+    def year_lookup_bounds(self, value): 
+        return [datetime.datetime(value, 1, 1, 0, 0, 0, 0),
+                datetime.datetime(value+1, 1, 1, 0, 0, 0, 0)]
+
 class DatabaseClient(BaseDatabaseClient):
     pass
 

File db/basecompiler.py

     def _normalize_lookup_value(self, value, annotation, lookup_type):
         # Django fields always return a list (see Field.get_db_prep_lookup)
         # except if get_db_prep_lookup got overridden by a subclass
-        if lookup_type not in ('in', 'range') and isinstance(value, (tuple, list)):
+        if lookup_type not in ('in', 'range', 'year') and isinstance(value, (tuple, list)):
             if len(value) > 1:
                 raise DatabaseError('Filter lookup type was: %s. Expected the '
                                 'filters value not to be a list. Only "in"-filters '

File db/compiler.py

     'isnull': None,
     'startswith': None,
     'range': None,
+    'year': None,
 
     # TODO: support these filters
     # in
                 query["%s %s" % (column, op)] = self.convert_value_for_db(
                     db_type, value)
                 continue
-            elif lookup_type == 'range':
+            elif lookup_type in ('range', 'year'):
                 op = '>='
                 query["%s %s" % (column, op)] = self.convert_value_for_db(
                     db_type, value[0])
-                op = '<='
+                op = '<=' if lookup_type == 'range' else '<'
                 query["%s %s" % (column, op)] = self.convert_value_for_db(
                     db_type, value[1])
                 continue

File tests/filter.py

-from .testmodels import FieldsWithOptionsModel, EmailModel, OrderedModel
+from .testmodels import FieldsWithOptionsModel, EmailModel, DateTimeModel, OrderedModel
 import datetime, time
 from django.test import TestCase
 from django.db.models import Q
     floats = [5.3, 2.6, 9.1, 1.58]
     emails = ['app-engine@scholardocs.com', 'sharingan@uchias.com',
         'rinnengan@sage.de', 'rasengan@naruto.com']
-
+    datetimes = [datetime.datetime(2010, 1, 1, 0, 0, 0, 0),
+        datetime.datetime(2010, 12, 31, 23, 59, 59, 999999),
+        datetime.datetime(2011, 1, 1, 0, 0, 0, 0),
+        datetime.datetime(2013, 7, 28, 22, 30, 20, 50)]
+    
     def setUp(self):
-        for index, (float, email) in enumerate(zip(FilterTest.floats,
-                FilterTest.emails)):
+        for index, (float, email, datetime_value) in enumerate(zip(FilterTest.floats,
+                FilterTest.emails, FilterTest.datetimes)):
             # ensure distinct times when saving entities
             time.sleep(0.01)
             self.last_save_time = datetime.datetime.now().time()
                                    time=self.last_save_time,
                                    foreign_key=ordered_instance).save()
             EmailModel(email=email).save()
+            DateTimeModel(datetime=datetime_value).save()
 
     def test_startswith(self):
         self.assertEquals([entity.email for entity in
                             time__range=(start_time, self.last_save_time)).order_by('time')],
                             ['app-engine@scholardocs.com', 'sharingan@uchias.com',
                             'rinnengan@sage.de', 'rasengan@naruto.com',])
-                            
+
+    def test_date(self):
+        # test year on date range boundaries
+        self.assertEquals([entity.datetime for entity in
+                            DateTimeModel.objects.filter(
+                            datetime__year=2010).order_by('datetime')],
+                            [datetime.datetime(2010, 1, 1, 0, 0, 0, 0),
+                             datetime.datetime(2010, 12, 31, 23, 59, 59, 999999),])
+
+        # test year on non boundary date
+        self.assertEquals([entity.datetime for entity in
+                            DateTimeModel.objects.filter(
+                            datetime__year=2013).order_by('datetime')],
+                            [datetime.datetime(2013, 7, 28, 22, 30, 20, 50),])
+
     def test_latest(self):
         self.assertEquals(FieldsWithOptionsModel.objects.latest('time').floating_point,
                             1.58)

File tests/testmodels.py

 class EmailModel(models.Model):
     email = models.EmailField()
 
+class DateTimeModel(models.Model):
+    datetime = models.DateTimeField()
+
 class FieldsWithoutOptionsModel(models.Model):
     datetime = models.DateTimeField()
     date = models.DateField()