У мене є поле в одній моделі, як:
class Sample(models.Model):
date = fields.DateField(auto_now=False)
Тепер мені потрібно фільтрувати об’єкти за діапазоном дат.
Як я фільтрую всі об'єкти, які мають дату між 1-Jan-2011
і 31-Jan-2011
?
У мене є поле в одній моделі, як:
class Sample(models.Model):
date = fields.DateField(auto_now=False)
Тепер мені потрібно фільтрувати об’єкти за діапазоном дат.
Як я фільтрую всі об'єкти, які мають дату між 1-Jan-2011
і 31-Jan-2011
?
Відповіді:
Використовуйте
Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])
Або якщо ви просто намагаєтесь фільтрувати місяць:
Sample.objects.filter(date__year='2011',
date__month='01')
Як сказав Бернхард Валлант, якщо ви хочете набір запитів, який виключає, specified range ends
ви повинні розглянути його рішення , яке використовує gt / lt (більше-ніж / менше-ніж).
__range
включає межі (як, наприклад, sql BETWEEN
), якщо ви не хочете, щоб межі були включені, вам доведеться перейти з моїм рішенням gt / lt ...
order_by
над створеним QuerySet
вищезгаданим filter
. Я не користувався Джанго роками.
Ви можете використовувати джангоfilter
з datetime.date
об'єктами :
import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
sampledate__lte=datetime.date(2011, 1, 31))
Виконуючи діапазони джанго з фільтром, переконайтеся, що ви знаєте різницю між використанням об’єкта дати та об'єктом дати. __range включається в дати, але якщо ви використовуєте об'єкт datetime для кінцевої дати, він не буде включати записи для цього дня, якщо час не встановлено.
startdate = date.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])
повертає всі записи від початкового до кінця оновлення, включаючи записи в ці дати. Поганий приклад, оскільки це повернення записів на тиждень у майбутнє, але ви отримуєте дрейф.
startdate = datetime.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])
бракує записів на суму 24 години залежно від того, на який час встановлено час для полів дати.
date
об’єкт: >>> from datetime import date
>>> startdate = date.today()
Ви можете обійти "невідповідність імпедансу", викликану недостатньою точністю в DateTimeField/date
порівнянні об'єктів - що може статися при використанні діапазону - за допомогою datetime.timedelta, щоб додати день до останньої дати в діапазоні. Це працює так:
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])
Як обговорювалося раніше, не роблячи щось подібне, записи ігноруються в останній день.
Відредагований, щоб уникнути використання datetime.combine
- здається, більш логічним дотримуватися екземплярів дати при порівнянні з DateTimeField
, а не возитися з викинутими (і плутати) datetime
об'єктами. Подальше пояснення див. У коментарях нижче.
Example.objects.filter(created__range=[date(2014, 1, 1), date(2014, 2, 1)])
не включатимуться об’єкти, створені на date(2014, 2, 1)
, як @cademan пояснив корисно. Але якщо ви збільшили дату закінчення, додавши один день, ви отримаєте набір запитів, що охоплюють ці відсутні об'єкти (і зручно опускати об'єкти, створені date(2014, 2, 2)
через ту саму вигадку). Прикра тут - те, що вказаний діапазон "посібника" created__gte ... created__lte=date(2014, 2, 1)
також не працює, що, безумовно, контр-інтуїтивно зрозумілий IMHO.
Це просто,
YourModel.objects.filter(YOUR_DATE_FIELD__date=timezone.now())
Працює для мене
Щоб зробити його більш гнучким, ви можете сконструювати FilterBackend, як показано нижче:
class AnalyticsFilterBackend(generic_filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
predicate = request.query_params # or request.data for POST
if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is not None:
queryset = queryset.filter(your_date__range=(predicate['from_date'], predicate['to_date']))
if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is None:
queryset = queryset.filter(your_date__gte=predicate['from_date'])
if predicate.get('to_date', None) is not None and predicate.get('from_date', None) is None:
queryset = queryset.filter(your_date__lte=predicate['to_date'])
return queryset
Дотепер актуальна і сьогодні. Ви також можете зробити:
import dateutil
import pytz
date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)