Phil Gyford
Phil Gyford

Reputation: 14594

In Django, filter a query set for two datetimes being within one day

I have a Django model like:

from django.db import models

class Person(models.Model):
    # ...
    last_login = models.DateTimeField(null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True)

I want to find all Persons where last_login is within one day of date_created.

So far I have:

from datetime import timedelta
from django.db.models import F

Person.objects.annotate(
    duration=F("last_login") - F("date_created")
).filter(duration__lte=timedelta(days=1))

But the tail end of the error when I do that is like:

  File ".../lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1316, in to_python
    parsed = parse_datetime(value)
  File ".../lib/python3.7/site-packages/django/utils/dateparse.py", line 107, in parse_datetime
    match = datetime_re.match(value)
TypeError: expected string or bytes-like object

I'm not sure what I'm doing wrong, probably with that timedelta(days=1).

Also (and I don't think this is the immediate error), I'm not sure if that query will take account of the fact that last_login could be None.

Upvotes: 1

Views: 37

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

You can filter with:

from datetime import timedelta
from django.db.models import F

Person.objects.filter(
    last_login__lte=F('date_created') + timedelta(days=1)
)

you can return records if last_login is None/NULL as well, with:

from datetime import timedelta
from django.db.models import F, Q

Person.objects.filter(
    Q(last_login__lte=F('date_created') + timedelta(days=1)) |
    Q(last_login=None)
)

Upvotes: 1

Related Questions