Loading AUTHORS +1 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,7 @@ answer newbie questions, and generally made Django that much better: John Paulett <john@paulett.org> John Shaffer <jshaffer2112@gmail.com> Jökull Sólberg Auðunsson <jokullsolberg@gmail.com> Jon Dufresne <jon.dufresne@gmail.com> Jonathan Buchanan <jonathan.buchanan@gmail.com> Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/> Jonathan Feignberg <jdf@pobox.com> Loading django/db/models/fields/__init__.py +142 −24 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from base64 import b64decode, b64encode from django.apps import apps from django.db import connection from django.db.models.lookups import default_lookups, RegisterLookupMixin from django.db.models.lookups import default_lookups, RegisterLookupMixin, Transform, Lookup from django.db.models.query_utils import QueryWrapper from django.conf import settings from django import forms Loading Loading @@ -724,7 +724,6 @@ class Field(RegisterLookupMixin): if lookup_type in { 'iexact', 'contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', 'month', 'day', 'week_day', 'hour', 'minute', 'second', 'isnull', 'search', 'regex', 'iregex', }: return value Loading @@ -732,12 +731,6 @@ class Field(RegisterLookupMixin): return self.get_prep_value(value) elif lookup_type in ('range', 'in'): return [self.get_prep_value(v) for v in value] elif lookup_type == 'year': try: return int(value) except ValueError: raise ValueError("The __year lookup type requires an integer " "argument") return self.get_prep_value(value) def get_db_prep_lookup(self, lookup_type, value, connection, Loading @@ -761,8 +754,7 @@ class Field(RegisterLookupMixin): sql, params = value._as_sql(connection=connection) return QueryWrapper(('(%s)' % sql), params) if lookup_type in ('month', 'day', 'week_day', 'hour', 'minute', 'second', 'search', 'regex', 'iregex', 'contains', if lookup_type in ('search', 'regex', 'iregex', 'contains', 'icontains', 'iexact', 'startswith', 'endswith', 'istartswith', 'iendswith'): return [value] Loading @@ -774,13 +766,6 @@ class Field(RegisterLookupMixin): prepared=prepared) for v in value] elif lookup_type == 'isnull': return [] elif lookup_type == 'year': if isinstance(self, DateTimeField): return connection.ops.year_lookup_bounds_for_datetime_field(value) elif isinstance(self, DateField): return connection.ops.year_lookup_bounds_for_date_field(value) else: return [value] # this isn't supposed to happen else: return [value] Loading Loading @@ -1302,13 +1287,6 @@ class DateField(DateTimeCheckMixin, Field): curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)) def get_prep_lookup(self, lookup_type, value): # For dates lookups, convert the value to an int # so the database backend always sees a consistent type. if lookup_type in ('month', 'day', 'week_day', 'hour', 'minute', 'second'): return int(value) return super(DateField, self).get_prep_lookup(lookup_type, value) def get_prep_value(self, value): value = super(DateField, self).get_prep_value(value) return self.to_python(value) Loading Loading @@ -2408,3 +2386,143 @@ class UUIDField(Field): } defaults.update(kwargs) return super(UUIDField, self).formfield(**defaults) class DateTransform(Transform): def as_sql(self, compiler, connection): sql, params = compiler.compile(self.lhs) lhs_output_field = self.lhs.output_field if isinstance(lhs_output_field, DateTimeField): tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None sql, tz_params = connection.ops.datetime_extract_sql(self.lookup_name, sql, tzname) params.extend(tz_params) else: # DateField and TimeField. sql = connection.ops.date_extract_sql(self.lookup_name, sql) return sql, params @cached_property def output_field(self): return IntegerField() class YearTransform(DateTransform): lookup_name = 'year' class YearLookup(Lookup): def year_lookup_bounds(self, connection, year): output_field = self.lhs.lhs.output_field if isinstance(output_field, DateTimeField): bounds = connection.ops.year_lookup_bounds_for_datetime_field(year) else: bounds = connection.ops.year_lookup_bounds_for_date_field(year) return bounds @YearTransform.register_lookup class YearExact(YearLookup): lookup_name = 'exact' def as_sql(self, compiler, connection): # We will need to skip the extract part and instead go # directly with the originating field, that is self.lhs.lhs. lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs) rhs_sql, rhs_params = self.process_rhs(compiler, connection) bounds = self.year_lookup_bounds(connection, rhs_params[0]) params.extend(bounds) return '%s BETWEEN %%s AND %%s' % lhs_sql, params class YearComparisonLookup(YearLookup): def as_sql(self, compiler, connection): # We will need to skip the extract part and instead go # directly with the originating field, that is self.lhs.lhs. lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs) rhs_sql, rhs_params = self.process_rhs(compiler, connection) rhs_sql = self.get_rhs_op(connection, rhs_sql) start, finish = self.year_lookup_bounds(connection, rhs_params[0]) params.append(self.get_bound(start, finish)) return '%s %s' % (lhs_sql, rhs_sql), params def get_rhs_op(self, connection, rhs): return connection.operators[self.lookup_name] % rhs def get_bound(self): raise NotImplementedError( 'subclasses of YearComparisonLookup must provide a get_bound() method' ) @YearTransform.register_lookup class YearGt(YearComparisonLookup): lookup_name = 'gt' def get_bound(self, start, finish): return finish @YearTransform.register_lookup class YearGte(YearComparisonLookup): lookup_name = 'gte' def get_bound(self, start, finish): return start @YearTransform.register_lookup class YearLt(YearComparisonLookup): lookup_name = 'lt' def get_bound(self, start, finish): return start @YearTransform.register_lookup class YearLte(YearComparisonLookup): lookup_name = 'lte' def get_bound(self, start, finish): return finish class MonthTransform(DateTransform): lookup_name = 'month' class DayTransform(DateTransform): lookup_name = 'day' class WeekDayTransform(DateTransform): lookup_name = 'week_day' class HourTransform(DateTransform): lookup_name = 'hour' class MinuteTransform(DateTransform): lookup_name = 'minute' class SecondTransform(DateTransform): lookup_name = 'second' DateField.register_lookup(YearTransform) DateField.register_lookup(MonthTransform) DateField.register_lookup(DayTransform) DateField.register_lookup(WeekDayTransform) TimeField.register_lookup(HourTransform) TimeField.register_lookup(MinuteTransform) TimeField.register_lookup(SecondTransform) DateTimeField.register_lookup(YearTransform) DateTimeField.register_lookup(MonthTransform) DateTimeField.register_lookup(DayTransform) DateTimeField.register_lookup(WeekDayTransform) DateTimeField.register_lookup(HourTransform) DateTimeField.register_lookup(MinuteTransform) DateTimeField.register_lookup(SecondTransform) django/db/models/lookups.py +0 −58 Original line number Diff line number Diff line import inspect from copy import copy from django.conf import settings from django.utils import timezone from django.utils.functional import cached_property from django.utils.six.moves import range Loading Loading @@ -408,11 +406,6 @@ class Between(BuiltinLookup): return "BETWEEN %s AND %s" % (rhs, rhs) class Year(Between): lookup_name = 'year' default_lookups['year'] = Year class Range(BuiltinLookup): lookup_name = 'range' Loading @@ -430,57 +423,6 @@ class Range(BuiltinLookup): default_lookups['range'] = Range class DateLookup(BuiltinLookup): def process_lhs(self, compiler, connection, lhs=None): from django.db.models import DateTimeField lhs, params = super(DateLookup, self).process_lhs(compiler, connection, lhs) if isinstance(self.lhs.output_field, DateTimeField): tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None sql, tz_params = connection.ops.datetime_extract_sql(self.extract_type, lhs, tzname) return connection.ops.lookup_cast(self.lookup_name) % sql, tz_params else: return connection.ops.date_extract_sql(self.lookup_name, lhs), [] def get_rhs_op(self, connection, rhs): return '= %s' % rhs class Month(DateLookup): lookup_name = 'month' extract_type = 'month' default_lookups['month'] = Month class Day(DateLookup): lookup_name = 'day' extract_type = 'day' default_lookups['day'] = Day class WeekDay(DateLookup): lookup_name = 'week_day' extract_type = 'week_day' default_lookups['week_day'] = WeekDay class Hour(DateLookup): lookup_name = 'hour' extract_type = 'hour' default_lookups['hour'] = Hour class Minute(DateLookup): lookup_name = 'minute' extract_type = 'minute' default_lookups['minute'] = Minute class Second(DateLookup): lookup_name = 'second' extract_type = 'second' default_lookups['second'] = Second class IsNull(BuiltinLookup): lookup_name = 'isnull' Loading docs/ref/models/querysets.txt +55 −8 Original line number Diff line number Diff line Loading @@ -2431,36 +2431,45 @@ numbers and even characters. year ~~~~ For date and datetime fields, an exact year match. Takes an integer year. For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year. Example:: Entry.objects.filter(pub_date__year=2005) Entry.objects.filter(pub_date__year__gte=2005) SQL equivalent:: SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31'; SELECT ... WHERE pub_date >= '2005-01-01'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: month month ~~~~~ For date and datetime fields, an exact month match. Takes an integer 1 (January) through 12 (December). For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December). Example:: Entry.objects.filter(pub_date__month=12) Entry.objects.filter(pub_date__month__gte=6) SQL equivalent:: SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12'; SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6'; (The exact SQL syntax varies for each database engine.) Loading @@ -2468,20 +2477,27 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: day day ~~~ For date and datetime fields, an exact day match. Takes an integer day. For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day. Example:: Entry.objects.filter(pub_date__day=3) Entry.objects.filter(pub_date__day__gte=3) SQL equivalent:: SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3'; SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3'; (The exact SQL syntax varies for each database engine.) Loading @@ -2492,12 +2508,17 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: week_day week_day ~~~~~~~~ For date and datetime fields, a 'day of the week' match. For date and datetime fields, a 'day of the week' match. Allows chaining additional field lookups. Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday). Loading @@ -2505,6 +2526,7 @@ Takes an integer value representing the day of week from 1 (Sunday) to 7 Example:: Entry.objects.filter(pub_date__week_day=2) Entry.objects.filter(pub_date__week_day__gte=2) (No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.) Loading @@ -2517,66 +2539,91 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: hour hour ~~~~ For datetime fields, an exact hour match. Takes an integer between 0 and 23. For datetime fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23. Example:: Event.objects.filter(timestamp__hour=23) Event.objects.filter(timestamp__hour__gte=12) SQL equivalent:: SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23'; SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: minute minute ~~~~~~ For datetime fields, an exact minute match. Takes an integer between 0 and 59. For datetime fields, an exact minute match. Allows chaining additional field lookups. Takes an integer between 0 and 59. Example:: Event.objects.filter(timestamp__minute=29) Event.objects.filter(timestamp__minute__gte=29) SQL equivalent:: SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29'; SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: second second ~~~~~~ For datetime fields, an exact second match. Takes an integer between 0 and 59. For datetime fields, an exact second match. Allows chaining additional field lookups. Takes an integer between 0 and 59. Example:: Event.objects.filter(timestamp__second=31) Event.objects.filter(timestamp__second__gte=31) SQL equivalent:: SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31'; SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: isnull isnull Loading docs/releases/1.9.txt +4 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,10 @@ Models * Added a system check to prevent defining both ``Meta.ordering`` and ``order_with_respect_to`` on the same model. * :lookup:`Date and time <year>` lookups can be chained with other lookups (such as :lookup:`exact`, :lookup:`gt`, :lookup:`lt`, etc.). For example: ``Entry.objects.filter(pub_date__month__gt=6)``. CSRF ^^^^ Loading Loading
AUTHORS +1 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,7 @@ answer newbie questions, and generally made Django that much better: John Paulett <john@paulett.org> John Shaffer <jshaffer2112@gmail.com> Jökull Sólberg Auðunsson <jokullsolberg@gmail.com> Jon Dufresne <jon.dufresne@gmail.com> Jonathan Buchanan <jonathan.buchanan@gmail.com> Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/> Jonathan Feignberg <jdf@pobox.com> Loading
django/db/models/fields/__init__.py +142 −24 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from base64 import b64decode, b64encode from django.apps import apps from django.db import connection from django.db.models.lookups import default_lookups, RegisterLookupMixin from django.db.models.lookups import default_lookups, RegisterLookupMixin, Transform, Lookup from django.db.models.query_utils import QueryWrapper from django.conf import settings from django import forms Loading Loading @@ -724,7 +724,6 @@ class Field(RegisterLookupMixin): if lookup_type in { 'iexact', 'contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', 'month', 'day', 'week_day', 'hour', 'minute', 'second', 'isnull', 'search', 'regex', 'iregex', }: return value Loading @@ -732,12 +731,6 @@ class Field(RegisterLookupMixin): return self.get_prep_value(value) elif lookup_type in ('range', 'in'): return [self.get_prep_value(v) for v in value] elif lookup_type == 'year': try: return int(value) except ValueError: raise ValueError("The __year lookup type requires an integer " "argument") return self.get_prep_value(value) def get_db_prep_lookup(self, lookup_type, value, connection, Loading @@ -761,8 +754,7 @@ class Field(RegisterLookupMixin): sql, params = value._as_sql(connection=connection) return QueryWrapper(('(%s)' % sql), params) if lookup_type in ('month', 'day', 'week_day', 'hour', 'minute', 'second', 'search', 'regex', 'iregex', 'contains', if lookup_type in ('search', 'regex', 'iregex', 'contains', 'icontains', 'iexact', 'startswith', 'endswith', 'istartswith', 'iendswith'): return [value] Loading @@ -774,13 +766,6 @@ class Field(RegisterLookupMixin): prepared=prepared) for v in value] elif lookup_type == 'isnull': return [] elif lookup_type == 'year': if isinstance(self, DateTimeField): return connection.ops.year_lookup_bounds_for_datetime_field(value) elif isinstance(self, DateField): return connection.ops.year_lookup_bounds_for_date_field(value) else: return [value] # this isn't supposed to happen else: return [value] Loading Loading @@ -1302,13 +1287,6 @@ class DateField(DateTimeCheckMixin, Field): curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)) def get_prep_lookup(self, lookup_type, value): # For dates lookups, convert the value to an int # so the database backend always sees a consistent type. if lookup_type in ('month', 'day', 'week_day', 'hour', 'minute', 'second'): return int(value) return super(DateField, self).get_prep_lookup(lookup_type, value) def get_prep_value(self, value): value = super(DateField, self).get_prep_value(value) return self.to_python(value) Loading Loading @@ -2408,3 +2386,143 @@ class UUIDField(Field): } defaults.update(kwargs) return super(UUIDField, self).formfield(**defaults) class DateTransform(Transform): def as_sql(self, compiler, connection): sql, params = compiler.compile(self.lhs) lhs_output_field = self.lhs.output_field if isinstance(lhs_output_field, DateTimeField): tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None sql, tz_params = connection.ops.datetime_extract_sql(self.lookup_name, sql, tzname) params.extend(tz_params) else: # DateField and TimeField. sql = connection.ops.date_extract_sql(self.lookup_name, sql) return sql, params @cached_property def output_field(self): return IntegerField() class YearTransform(DateTransform): lookup_name = 'year' class YearLookup(Lookup): def year_lookup_bounds(self, connection, year): output_field = self.lhs.lhs.output_field if isinstance(output_field, DateTimeField): bounds = connection.ops.year_lookup_bounds_for_datetime_field(year) else: bounds = connection.ops.year_lookup_bounds_for_date_field(year) return bounds @YearTransform.register_lookup class YearExact(YearLookup): lookup_name = 'exact' def as_sql(self, compiler, connection): # We will need to skip the extract part and instead go # directly with the originating field, that is self.lhs.lhs. lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs) rhs_sql, rhs_params = self.process_rhs(compiler, connection) bounds = self.year_lookup_bounds(connection, rhs_params[0]) params.extend(bounds) return '%s BETWEEN %%s AND %%s' % lhs_sql, params class YearComparisonLookup(YearLookup): def as_sql(self, compiler, connection): # We will need to skip the extract part and instead go # directly with the originating field, that is self.lhs.lhs. lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs) rhs_sql, rhs_params = self.process_rhs(compiler, connection) rhs_sql = self.get_rhs_op(connection, rhs_sql) start, finish = self.year_lookup_bounds(connection, rhs_params[0]) params.append(self.get_bound(start, finish)) return '%s %s' % (lhs_sql, rhs_sql), params def get_rhs_op(self, connection, rhs): return connection.operators[self.lookup_name] % rhs def get_bound(self): raise NotImplementedError( 'subclasses of YearComparisonLookup must provide a get_bound() method' ) @YearTransform.register_lookup class YearGt(YearComparisonLookup): lookup_name = 'gt' def get_bound(self, start, finish): return finish @YearTransform.register_lookup class YearGte(YearComparisonLookup): lookup_name = 'gte' def get_bound(self, start, finish): return start @YearTransform.register_lookup class YearLt(YearComparisonLookup): lookup_name = 'lt' def get_bound(self, start, finish): return start @YearTransform.register_lookup class YearLte(YearComparisonLookup): lookup_name = 'lte' def get_bound(self, start, finish): return finish class MonthTransform(DateTransform): lookup_name = 'month' class DayTransform(DateTransform): lookup_name = 'day' class WeekDayTransform(DateTransform): lookup_name = 'week_day' class HourTransform(DateTransform): lookup_name = 'hour' class MinuteTransform(DateTransform): lookup_name = 'minute' class SecondTransform(DateTransform): lookup_name = 'second' DateField.register_lookup(YearTransform) DateField.register_lookup(MonthTransform) DateField.register_lookup(DayTransform) DateField.register_lookup(WeekDayTransform) TimeField.register_lookup(HourTransform) TimeField.register_lookup(MinuteTransform) TimeField.register_lookup(SecondTransform) DateTimeField.register_lookup(YearTransform) DateTimeField.register_lookup(MonthTransform) DateTimeField.register_lookup(DayTransform) DateTimeField.register_lookup(WeekDayTransform) DateTimeField.register_lookup(HourTransform) DateTimeField.register_lookup(MinuteTransform) DateTimeField.register_lookup(SecondTransform)
django/db/models/lookups.py +0 −58 Original line number Diff line number Diff line import inspect from copy import copy from django.conf import settings from django.utils import timezone from django.utils.functional import cached_property from django.utils.six.moves import range Loading Loading @@ -408,11 +406,6 @@ class Between(BuiltinLookup): return "BETWEEN %s AND %s" % (rhs, rhs) class Year(Between): lookup_name = 'year' default_lookups['year'] = Year class Range(BuiltinLookup): lookup_name = 'range' Loading @@ -430,57 +423,6 @@ class Range(BuiltinLookup): default_lookups['range'] = Range class DateLookup(BuiltinLookup): def process_lhs(self, compiler, connection, lhs=None): from django.db.models import DateTimeField lhs, params = super(DateLookup, self).process_lhs(compiler, connection, lhs) if isinstance(self.lhs.output_field, DateTimeField): tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None sql, tz_params = connection.ops.datetime_extract_sql(self.extract_type, lhs, tzname) return connection.ops.lookup_cast(self.lookup_name) % sql, tz_params else: return connection.ops.date_extract_sql(self.lookup_name, lhs), [] def get_rhs_op(self, connection, rhs): return '= %s' % rhs class Month(DateLookup): lookup_name = 'month' extract_type = 'month' default_lookups['month'] = Month class Day(DateLookup): lookup_name = 'day' extract_type = 'day' default_lookups['day'] = Day class WeekDay(DateLookup): lookup_name = 'week_day' extract_type = 'week_day' default_lookups['week_day'] = WeekDay class Hour(DateLookup): lookup_name = 'hour' extract_type = 'hour' default_lookups['hour'] = Hour class Minute(DateLookup): lookup_name = 'minute' extract_type = 'minute' default_lookups['minute'] = Minute class Second(DateLookup): lookup_name = 'second' extract_type = 'second' default_lookups['second'] = Second class IsNull(BuiltinLookup): lookup_name = 'isnull' Loading
docs/ref/models/querysets.txt +55 −8 Original line number Diff line number Diff line Loading @@ -2431,36 +2431,45 @@ numbers and even characters. year ~~~~ For date and datetime fields, an exact year match. Takes an integer year. For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year. Example:: Entry.objects.filter(pub_date__year=2005) Entry.objects.filter(pub_date__year__gte=2005) SQL equivalent:: SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31'; SELECT ... WHERE pub_date >= '2005-01-01'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: month month ~~~~~ For date and datetime fields, an exact month match. Takes an integer 1 (January) through 12 (December). For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December). Example:: Entry.objects.filter(pub_date__month=12) Entry.objects.filter(pub_date__month__gte=6) SQL equivalent:: SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12'; SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6'; (The exact SQL syntax varies for each database engine.) Loading @@ -2468,20 +2477,27 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: day day ~~~ For date and datetime fields, an exact day match. Takes an integer day. For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day. Example:: Entry.objects.filter(pub_date__day=3) Entry.objects.filter(pub_date__day__gte=3) SQL equivalent:: SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3'; SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3'; (The exact SQL syntax varies for each database engine.) Loading @@ -2492,12 +2508,17 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: week_day week_day ~~~~~~~~ For date and datetime fields, a 'day of the week' match. For date and datetime fields, a 'day of the week' match. Allows chaining additional field lookups. Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday). Loading @@ -2505,6 +2526,7 @@ Takes an integer value representing the day of week from 1 (Sunday) to 7 Example:: Entry.objects.filter(pub_date__week_day=2) Entry.objects.filter(pub_date__week_day__gte=2) (No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.) Loading @@ -2517,66 +2539,91 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the current time zone before filtering. This requires :ref:`time zone definitions in the database <database-time-zone-definitions>`. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: hour hour ~~~~ For datetime fields, an exact hour match. Takes an integer between 0 and 23. For datetime fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23. Example:: Event.objects.filter(timestamp__hour=23) Event.objects.filter(timestamp__hour__gte=12) SQL equivalent:: SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23'; SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: minute minute ~~~~~~ For datetime fields, an exact minute match. Takes an integer between 0 and 59. For datetime fields, an exact minute match. Allows chaining additional field lookups. Takes an integer between 0 and 59. Example:: Event.objects.filter(timestamp__minute=29) Event.objects.filter(timestamp__minute__gte=29) SQL equivalent:: SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29'; SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: second second ~~~~~~ For datetime fields, an exact second match. Takes an integer between 0 and 59. For datetime fields, an exact second match. Allows chaining additional field lookups. Takes an integer between 0 and 59. Example:: Event.objects.filter(timestamp__second=31) Event.objects.filter(timestamp__second__gte=31) SQL equivalent:: SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31'; SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31'; (The exact SQL syntax varies for each database engine.) When :setting:`USE_TZ` is ``True``, values are converted to the current time zone before filtering. .. versionchanged:: 1.9 Allowed chaining additional field lookups. .. fieldlookup:: isnull isnull Loading
docs/releases/1.9.txt +4 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,10 @@ Models * Added a system check to prevent defining both ``Meta.ordering`` and ``order_with_respect_to`` on the same model. * :lookup:`Date and time <year>` lookups can be chained with other lookups (such as :lookup:`exact`, :lookup:`gt`, :lookup:`lt`, etc.). For example: ``Entry.objects.filter(pub_date__month__gt=6)``. CSRF ^^^^ Loading