Mam pole w jednym modelu, takim jak:
class Sample(models.Model):
date = fields.DateField(auto_now=False)
Teraz muszę filtrować obiekty według zakresu dat.
Jak filtrować wszystkie obiekty z datą pomiędzy 1-Jan-2011
i 31-Jan-2011
?
Mam pole w jednym modelu, takim jak:
class Sample(models.Model):
date = fields.DateField(auto_now=False)
Teraz muszę filtrować obiekty według zakresu dat.
Jak filtrować wszystkie obiekty z datą pomiędzy 1-Jan-2011
i 31-Jan-2011
?
Odpowiedzi:
Posługiwać się
Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])
Lub jeśli próbujesz po prostu filtrować miesiąc:
Sample.objects.filter(date__year='2011',
date__month='01')
Jak powiedział Bernhard Vallant, jeśli chcesz zestawu zapytań wykluczającego specified range ends
, powinieneś rozważyć jego rozwiązanie , które wykorzystuje gt / lt (większe niż / mniejsze niż).
__range
obejmuje granice (jak na SQL BETWEEN
), jeśli nie chcesz granice włączone trzeba by iść z mojego GT / rozwiązanie lt ...
order_by
ponad wygenerowane QuerySet
przez wyżej wymienione filter
. Nie używałem Django od lat.
Możesz używać djangofilter
z datetime.date
obiektami :
import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
sampledate__lte=datetime.date(2011, 1, 31))
Robiąc zakresy django z filtrem upewnij się, że znasz różnicę między użyciem obiektu daty a obiektem daty i godziny. __zakres obejmuje daty, ale jeśli użyjesz obiektu datetime dla daty końcowej, nie będzie zawierał wpisów dla tego dnia, jeśli czas nie zostanie ustawiony.
startdate = date.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])
zwraca wszystkie wpisy od daty początkowej do końcowej, w tym pozycje z tych dat. Zły przykład, ponieważ zwraca on wpisy w tydzień w przyszłości, ale dostajesz dryf.
startdate = datetime.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])
będą brakować 24-godzinne wpisy, w zależności od ustawionego czasu dla pól daty.
date
obiekt: >>> from datetime import date
>>> startdate = date.today()
Można obejść problem „niedopasowania impedancji” spowodowanego brakiem precyzji w DateTimeField/date
porównywaniu obiektów - który może wystąpić w przypadku użycia zakresu - za pomocą datetime.timedelta, aby dodać dzień do ostatniej daty w zakresie. Działa to jak:
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])
Jak wspomniano wcześniej, bez robienia czegoś takiego, rekordy są ignorowane ostatniego dnia.
Edytowane, aby uniknąć użycia datetime.combine
- wydaje się bardziej logiczne, aby trzymać się instancji daty podczas porównywania z DateTimeField
, zamiast bawić się w rzucane (i mylące) datetime
obiekty. Zobacz dalsze wyjaśnienia w komentarzach poniżej.
Example.objects.filter(created__range=[date(2014, 1, 1), date(2014, 2, 1)])
nie będzie to obiekty utworzone na date(2014, 2, 1)
, jak @cademan wyjaśnił usłużnie. Ale jeśli zwiększysz datę końcową, dodając jeden dzień, otrzymasz zestaw zapytań obejmujący brakujące obiekty (i wygodnie pominiesz obiekty utworzone na podstawie date(2014, 2, 2)
tego samego dziwactwa). Irytujące jest to, że określony „manualny” zakres created__gte ... created__lte=date(2014, 2, 1)
również nie działa, co zdecydowanie jest sprzeczne z intuicją IMHO.
Jest proste,
YourModel.objects.filter(YOUR_DATE_FIELD__date=timezone.now())
Pracuje dla mnie
Aby uczynić go bardziej elastycznym, możesz zaprojektować FilterBackend w następujący sposób:
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
Nadal aktualne dzisiaj. Możesz także:
import dateutil
import pytz
date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)