Query annotation with date difference

5,161 views
Skip to first unread message

Yoann Duriaud

unread,
Jul 30, 2016, 4:41:21 PM7/30/16
to Django users
Hello,
I would like to annotate a query with the following expression: ([Due Date] - [Now])/[Interval]. [Due Date] and [Interval] are fields from the database, while [Now] should be "equal" to timezone.now().

So this would look like:
.annotate(ratio=(F('due_date')-timezone.now())/F('Interval'))

but this does not work. Does someone know how the expression should be written (if it is indeed feasible with Django ORM)?

Thanks for your help!

Yoann

Constantine Covtushenko

unread,
Jul 31, 2016, 3:25:58 AM7/31/16
to django...@googlegroups.com
Hi Yoann,

I am not sure exactly but believes you are on the right way.
Try improve your expression with ExpressionWrapper, as said here.
Probably the problem is that you use values of different types in your expression.

Regards

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/03dedd39-142f-468a-b6fd-b7ec551862e8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yoann Duriaud

unread,
Aug 1, 2016, 4:25:51 PM8/1/16
to Django users, constantine...@gmail.com
Thanks for the tip, but besides defining the type of the output it is unclear how this can be used to perform a date difference operation.

What I would need is to convert timezone.now() into a date constant that can be understood by the database, whatever the database is. If I leave it as it is, I get the str() conversion, which is meaningless for the database. Even if I find some format dd-mm-yyyy that works with a given database, I wouldn't be sure that it works with other databases. I need the ORM to perform the conversion Date Object -> Database date constant.

Then comes the date difference operation. Same thing: either the database understands the minus sign with date format, or it doesn't and need some DATEDIFF operator. Again I would need the ORM to explicitly set the right operator.
My guess at the moment is that this cannot be achieved with Django ORM. I may apply the dict method and work with the dictionary instead, so that I can add custom fields more easily.

Yoann

Constantine Covtushenko

unread,
Aug 2, 2016, 1:36:59 AM8/2/16
to django...@googlegroups.com
Hi,

I am not cleat of what you suggested as a dictionary method and how you are going to use it.

But any way let me check my guesses and I will be back.

Constantine Covtushenko

unread,
Aug 2, 2016, 3:46:41 PM8/2/16
to django...@googlegroups.com
Ok, I am ready.

I did exactly as I suggested and got successful result.
Please check screenshots below:
on admin:
Inline image 1
on table view with annotated field:
Inline image 2

were
-model
class Entity(models.Model):
due_date = models.DateTimeField(default=timezone.now())
interval = models.PositiveSmallIntegerField(default=2)

objects = EntityManager()

and manager
class EntityManager(models.Manager):
def get_items(self):
return self.all().annotate(
ratio=models.ExpressionWrapper(
(models.F('due_date') - timezone.now())/models.F('interval'), models.DateTimeField()))
As we can see no dates format problem at all.
Django works as expected - perfectly!

Hope that helps.

Regards,

Yoann Duriaud

unread,
Aug 3, 2016, 5:20:44 PM8/3/16
to Django users
Thanks, unfortunately not so great on my side:

I added in the query (forgetting the division for now):

.annotate(ratio=ExpressionWrapper(F('due_date')-timezone.now(), DateTimeField()))


which leads to the following statement in the query:
 
("contentstatus"."due_date" - 2016-08-03 21:05:10.743799+00:00) AS "ratio"


This is not a valid SQL statement (at least for SQLite) and leads to the following error message when the query is evaluated:

Exception Type:

TypeError
Exception Value:

expected string or bytes-like object

Any idea what I get this behavior?

Yoann

Constantine Covtushenko

unread,
Aug 3, 2016, 5:34:33 PM8/3/16
to django...@googlegroups.com
Sorry, I did not specify.
I have been using 'Postgresql' with 'psycopg2 v.2.6.2'.
They gave me those results.

Also here is a sql query given from log:
SELECT "test_app_entity"."id", "test_app_entity"."due_date", "test_app_entity"."interval", (("test_app_entity"."due_date" - '2016-08-03T21:31:58.325549+00:00'::timestamptz) / "test_app_entity"."interval") AS "ratio" FROM "test_app_entity"; args=(datetime.datetime(2016, 8, 3, 21, 31, 58, 325549, tzinfo=<UTC>),)

That is all that I can say at the moment.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Peter of the Norse

unread,
Sep 4, 2016, 1:34:52 PM9/4/16
to django...@googlegroups.com

from django.db.models.functions import Now
.annotate(ratio=(F(‘due_date')-Now())/F('Interval'))


For more options, visit https://groups.google.com/d/optout.

Peter of the Norse



Reply all
Reply to author
Forward
0 new messages