#27473: Use/enable db.models.functions.Extract with/for DurationFields
-------------------------------------+-------------------------------------
               Reporter:  Daniel     |          Owner:  nobody
  Hahler                             |
                   Type:  New        |         Status:  new
  feature                            |
              Component:  Database   |        Version:  1.10
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I am trying to use `Extract` on a duration field, but this results in
 `ValueError: Extract input expression must be DateField, DateTimeField, or
 TimeField.`:

 {{{
 qs = qs.annotate(
     speed=Sum(
         F('distance_in_meters') * Value(3.6) /
             Extract(F('duration_in_seconds'), 'epoch'),
         output_field=FloatField()),
 )
 }}}


 The following patch however makes it work on PostgreSQL, so it should be
 considered to be enabled there - in case other DB backends do not support
 it:

 {{{
 diff --git i/django/db/models/functions/datetime.py
 w/django/db/models/functions/datetime.py
 index 2980460..3266ef6 100644
 --- i/django/db/models/functions/datetime.py
 +++ w/django/db/models/functions/datetime.py
 @@ -5,6 +5,7 @@
  from django.conf import settings
  from django.db.models import (
      DateField, DateTimeField, IntegerField, TimeField, Transform,
 +    DurationField,
  )
  from django.db.models.lookups import (
      YearExact, YearGt, YearGte, YearLt, YearLte,
 @@ -52,6 +53,8 @@ def as_sql(self, compiler, connection):
              sql = connection.ops.date_extract_sql(self.lookup_name, sql)
          elif isinstance(lhs_output_field, TimeField):
              sql = connection.ops.time_extract_sql(self.lookup_name, sql)
 +        elif isinstance(lhs_output_field, DurationField):
 +            sql = connection.ops.date_extract_sql(self.lookup_name, sql)
          else:
              # resolve_expression has already validated the output_field
 so this
              # assert should never be hit.
 @@ -61,7 +64,7 @@ def as_sql(self, compiler, connection):
      def resolve_expression(self, query=None, allow_joins=True,
 reuse=None, summarize=False, for_save=False):
          copy = super(Extract, self).resolve_expression(query,
 allow_joins, reuse, summarize, for_save)
          field = copy.lhs.output_field
 -        if not isinstance(field, (DateField, DateTimeField, TimeField)):
 +        if not isinstance(field, (DateField, DateTimeField, TimeField,
 DurationField)):
              raise ValueError('Extract input expression must be DateField,
 DateTimeField, or TimeField.')
          # Passing dates to functions expecting datetimes is most likely a
 mistake.
          if type(field) == DateField and copy.lookup_name in ('hour',
 'minute', 'second'):
 }}}

 Am I missing something?
 What needs to be done to get it enabled for DurationFields?

--
Ticket URL: <https://code.djangoproject.com/ticket/27473>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/050.1486dae47d5974264682a7598181b24c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to