2012-06-28 14 views
12

Non riesco a rappresentare logicamente quanto segue in un filtro Django. Ho un modello di 'evento', e un modello posizione, che può essere rappresentato come:Eventi di filtro Django che si verificano oggi

class Location(models.Model): 
    name = models.CharField(max_length=255) 

class Event(models.Model): 
    start_date = models.DateTimeField() 
    end_date = models.DateTimeField() 
    location = models.ForeignKeyField(Location) 

    objects = EventManager() 

per un determinato luogo, voglio selezionare tutti gli eventi che si verificano oggi. Ho provato varie strategie tramite un metodo 'bookings_today' nel EventManager, ma la sintassi del filtro destra mi sfugge:

class EventManager(models.Manager): 
    def bookings_today(self, location_id): 
     bookings = self.filter(location=location_id, start=?, end=?) 

data() fallisce in quanto questo azzera i tempi, e l'ora durante il giorno è fondamentale per l'app, lo stesso vale per il minimo e il massimo delle date e utilizzandole come fermalibri. In aggiunta, ci sono più possibili configurazioni valide:

start_date < today, end_date during today 
start_date during today, end_date during today 
start_date during today, end_date after today 

Ho bisogno di codificare un insieme di diverse opzioni o c'è un metodo più semplice ed elegante?

+1

uno sguardo al l'operatore di intervallo per tra SQL puoi anche questa risposta da @danielroseman: http://stackoverflow.com/questions/3963201/ how-do-you-select-between-two-dates-with-django –

risposta

19

Avrete bisogno di due distinte soglie datetime - today_start e today_end:

from datetime import datetime, timedelta, time 

today = datetime.now().date() 
tomorrow = today + timedelta(1) 
today_start = datetime.combine(today, time()) 
today_end = datetime.combine(tomorrow, time()) 

Tutto ciò accade oggi abbia avuto inizio prima today_ende conclusa dopotoday_start, quindi:

class EventManager(models.Manager): 
    def bookings_today(self, location_id): 
     # Construction of today_end/today_start as above, omitted for brevity 
     return self.filter(location=location_id, start__lte=today_end, end__gte=today_start) 

(P.S. Avere un DateTimeField (non un DateField) chiamato foo_date è irritante fuorviante - prendere in considerazione solo start e end ...)

+0

Aha - geniale! Grazie. – jvc26

+1

'datetime.now()' per favore – lajarre

1

Che ne dici di questo: pub_date__gte=datetime(2005, 1, 1)? Utilizzare _gte e __lte per limitare l'inizio e la fine in un giorno utilizzando il metodo di concatenamento.

Forse qualcosa come self.filter(start__gte=datetime(2005, 1, 1)).filter(end__lte=datetime(2005, 1, 1)). lte corrisponde a minore o uguale a, gte corrisponde a maggiore o uguale a.

Lo trovo in django doc.

5

È necessario utilizzare una gamma lì come questo:

class EventManager(models.Manager): 
    def bookings_today(self, location_id): 
     from datetime import datetime 
     now = datetime.now() 
     bookings = self.filter(location=location_id, start__lte=now, end__gte=now) 
     return bookings 
+0

Cosa succede se l'inizio e la fine dell'evento rientrano oggi? questo non lo prenderebbe in considerazione - potrebbe essere un momento * di headdesk *, ma mettere end__gte = today e start__lte = oggi risolverlo? – jvc26

+0

Sì, hai ragione. end__gte = today e start__lte = today dovrebbe essere usato. –

+0

A destra, questo in realtà non funziona, dato che la data di inizio potrebbe cadere prima dell'inizio di oggi, o dopo di essa, e date.today() non appare in mesh con gli oggetti datetime in termini di uguaglianza durante la selezione. – jvc26

0

penso che esclude è il tuo amico qui!

today = datetime.date.today() 
tomorrow = today + datetime.timedelta(days = 1) 
self.filter(location = location_id).exclude(end_date__lt = today).exclude(start_date__gte = tomorrow) 
1

Nessuna delle risposte che ho visto è a conoscenza fuso orario.

Perché non basta fare questo, invece:

from django.utils import timezone 

class EventManager(models.Manager): 
    def bookings_today(self, location_id): 
     bookings = self.filter(location=location_id, start__gte=timezone.now().replace(hour=0, minute=0, second=0), end__lte=timezone.now().replace(hour=23, minute=59, second=59)) 
Problemi correlati