6π
7 days == 1 day * 7
F
is deep-black Django magic and the objects that encounter it
must belong to the appropriate magical circles to handle it.
In your case, django.db.models.query.filter
knows about F
, but datetime.timedelta
does not.
Therefore, you need to keep the F
out of the timedelta
argument list.
Fortunately, multiplication of timedelta * int
is supported by F
,
so the following can work:
Process.objects.filter(date_up__lte=datetime.now()-timedelta(days=1)*F('days_activation'))
As it turns out, this will work with PostgreSQL, but will not work with SQlite (for which Django 1.11 only supports +
and -
for timedelta
,
perhaps because of a corresponding SQlite limitation).
2π
You are mixing two layers: run-time layer and the database layer. F
function is just a helper which allows you to build slightly more complex queries with django ORM. You are using timedelta
and F
together and expecting that django ORM will be smart enough to convert these things to raw SQL, but it canβt, as I see. Maybe I am wrong and do not know something about django ORM.
Anyway, you can rewrite you ORM call with extra extra and build the WHERE clause manually using native SQL functions which equals to datetime.now()
and timedelta
.
- Django Tables β Column Filtering
- Is the Global Request variable in Python/Django available?
- Django: [email protected] in admin
- In Django QuerySet, how do I do negation in the filter?
2π
You have to extend Aggregate. Do like below:
from django.db import models as DM
class BaseSQL(object):
function = 'DATE_SUB'
template = '%(function)s(NOW(), interval %(expressions)s day)'
class DurationAgr(BaseSQL, DM.Aggregate):
def __init__(self, expression, **extra):
super(DurationAgr, self).__init__(
expression,
output_field=DM.DateTimeField(),
**extra
)
Process.objects.filter(date_up__lte=DurationAgr('days_activation'))
Hopefully, It will work for you. π
0π
I tried to use solution by Lutz Prechelt above, but got MySQL syntax error.
Itβs because we canβt perform arithmetic operations with INTERVAL in MySQL.
So, for MySQL my solution is create a custom DB function:
class MysqlSubDate(Func):
function = 'SUBDATE'
output_field = DateField()
Example of usage:
.annotate(remainded_days=MysqlSubDate('end_datetime', F('days_activation')))
Also you can use timedelta, it will be converted into INTERVAL
.annotate(remainded_days=MysqlSubDate('end_datetime', datetime.timedelta(days=10)))
- How do I use .env in Django?
- Django-ajax-selects example usage
- How to export Django model data into CSV file
- Django allauth not sending links with https
- Django Rest Framework: Output in JSON to the browser by default