it-swarm.com.de

Django-Datenbankabfrage: Wie Objekte nach Datumsbereich filtern?

Ich habe ein Feld in einem Modell wie

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

Jetzt muss ich die Objekte nach einem Datenbereich filtern, z. B. alle Objekte, deren Datum zwischen dem 1. Januar 2011 und dem 31. Januar 2011 liegt.

Danke für Ihre Hilfe!

181
user469652

Benutzen 

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

Oder wenn Sie nur monatlich filtern möchten: 

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

Bearbeiten

Wie Bernhard Vallant sagte, wenn Sie ein Abfrageset wünschen, das den specified range ends ausschließt, sollten Sie seine Lösung betrachten, die gt/lt (größer als/kleiner als) verwendet.

325
crodjer

Sie können Djangos filter mit datetime.date Objekten verwenden:

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

Wenn Sie Django-Bereiche mit einem Filter verwenden, stellen Sie sicher, dass Sie den Unterschied zwischen der Verwendung eines Datumsobjekts und eines Datumszeitobjekts kennen. __range ist an Datumsangaben inklusive, aber wenn Sie ein Datumszeitobjekt für das Enddatum verwenden, werden die Einträge für diesen Tag nicht berücksichtigt, wenn die Uhrzeit nicht festgelegt ist.

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

gibt alle Einträge vom Startdatum bis zum Enddatum zurück, einschließlich der Einträge an diesen Daten. Ein schlechtes Beispiel, da dies eine Woche in der Zukunft Einträge zurückgibt, aber Sie bekommen die Drift.

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

es fehlen Einträge für 24 Stunden, abhängig davon, wie der Zeitpunkt für die Datumsfelder eingestellt ist.

71
cademan

Sie können die "Unstimmigkeit der Impedanz" umgehen, die durch die ungenaue Genauigkeit des DateTimeField/date-Objektvergleichs verursacht wird. Dies kann auftreten, wenn Sie range - verwenden, indem Sie einen datetime.timedelta verwenden, um einen Tag mit der letzten Dauer hinzuzufügen Datum im Bereich. Das funktioniert wie:

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])

Wie bereits erwähnt, werden Datensätze am letzten Tag ignoriert, ohne etwas davon zu tun.

Um die Verwendung von datetime.combine zu vermeiden, scheint es logischer zu sein, beim Vergleich mit einer DateTimeField bei Datumsinstanzen zu bleiben, anstatt mit wegwerfenden (und verwirrenden) datetime-Objekten herumzuspielen. Weitere Erläuterungen finden Sie in den Kommentaren unten.

16
trojjer

Ist einfach,  

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

Funktioniert bei mir

5

Um es flexibler zu gestalten, können Sie ein FilterBackend wie folgt entwerfen:

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
0
saran3h

Noch heute relevant ..__ Sie können auch tun:

import dateutil
import pytz

date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)
0
Bhavik Shah