Home » Python » Django database query: How to filter objects by date range?

Django database query: How to filter objects by date range?

Posted by: admin November 1, 2017 Leave a comment

Questions:

I’ve got a field in one model like

class Sample(models.Model):
    date = fields.DateField(auto_now=False)

Now, I need to filter the objects by a data range, for example, all the objects that has date between 1 Jan 2011 to 31 Jan 2011?

Thanks for your help!

Answers:

Use

Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])

Or if you are just trying to filter month wise:

Sample.objects.filter(date__year='2011', 
                      date__month='01')

Edit

As Bernhard Vallant said, if you want a queryset which excludes the specified range ends you should consider his solution, which utilizes gt/lt (greater-than/less-than).

Questions:
Answers:

You can use django’s filter with datetime.date objects:

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
                                sampledate__lte=datetime.date(2011, 1, 31))

Questions:
Answers:

When doing django ranges with a filter make sure you know the difference between using a date object vs a datetime object. __range is inclusive on dates but if you use a datetime object for the end date it will not include the entries for that day if the time is not set.

    startdate = date.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

returns all entries from startdate to enddate including entries on those dates. Bad example since this is returning entries a week into the future, but you get the drift.

    startdate = datetime.today()
    enddate = startdate + timedelta(days=6)
    Sample.objects.filter(date__range=[startdate, enddate])

will be missing 24 hours worth of entries depending on what the time for the date fields is set to.

Questions:
Answers:

You can get around the “impedance mismatch” caused by the lack of precision in the DateTimeField/date object comparison — that can occur if using range — by using a datetime.timedelta to add a day to last date in the range. This works like:

start = date(2012, 12, 11)
end = date(2012, 12, 18)
new_end = end + datetime.timedelta(days=1)

ExampleModel.objects.filter(some_datetime_field__range=[start, new_end])

As discussed previously, without doing something like this, records are ignored on the last day.

Edited to avoid the use of datetime.combine — seems more logical to stick with date instances when comparing against a DateTimeField, instead of messing about with throwaway (and confusing) datetime objects. See further explanation in comments below.

Questions:
Answers:

Works for me

YourModel.objects.filter(date__date=timezone.now())