2012-05-09 14 views
10

Ho un modello che contiene datefield. Sto cercando di ottenere il set di query di quel modello che contiene la settimana corrente (inizia il lunedì).Filtraggio del queryset Django secondo il numero ISO della settimana

Quindi dal momento che Django datefield contiene il semplice modello datetime.date, ho ipotizzato di filtrare utilizzando .isocalendar(). Logicamente è esattamente quello che voglio senza paragoni e calcoli extra entro l'attuale giorno della settimana.

Quindi quello che voglio fare in sostanza, è la forza .filter dichiarazione a comportarsi in questa logica:

if model.date.isocalendar()[2] == datetime.date.today().isocalendar()[2] 
    ... 

Ma come scriverlo dentro dichiarazione filtro? .filter(model__date__isocalendar=datetime.date.today().isocalendar()) darà risultati errati (come il confronto con oggi non questa settimana).

Come scavare vero http://docs.python.org/library/datetime.html non ho notato tutte le altre opzioni giorno della settimana ...

Nota da documentazione:

date.isocalendar() Restituisce una tupla di 3 elementi (anno ISO , Numero della settimana ISO, giorno ISO ).

Aggiornamento:

Anche se non mi piaceva la soluzione di utilizzare gamme Eppure è l'opzione migliore. Tuttavia nel mio caso ho fatto una variabile che segna l'inizio della settimana e ho un valore maggiore o uguale perché se sto cercando una partita per la settimana corrente. In caso di dare il numero della settimana richiederebbe entrambe le estremità.

today = datetime.date.today() 
monday = today - datetime.timedelta(days=today.weekday()) 

... \ 
.filter(date__gte=monday) 
+0

Io non so se il supporto ORM che, ma si può fallback a query raw se non https://docs.djangoproject.com/en/dev/topics/db/sql/ – dm03514

+0

Sono a conoscenza di questa opzione dm03514, ma preferisco scrivere il mio filtro quindi. Anche questa è un'opzione, ma sto chiedendo di sapere se è possibile farlo utilizzando le azioni predefinite in Django senza estenderlo. – JackLeo

+1

btw c'è un buon modulo dateutil Python che potrebbe essere utile http://pypi.python.org/pypi/python-dateutil – aisbaa

risposta

8

Non riuscirai a farlo. Ricorda che non è solo un problema di ciò che Python supporta, Django deve comunicare il filtro al database e il database non supporta calcoli di date così complessi. È possibile possibile utilizzare __range, con una data di inizio e una data di fine.

+0

Sì, vorrei usare anche * __ intervallo *, forse l'evento aggiungere il ModelManager personalizzato e il Queryset personalizzato con * settimana (date_field = (2012, 18)) * metodo. – aisbaa

+0

Conosco l'opzione intervallo, ma lo stavo evitando a causa del conteggio delle azioni necessario per ottenere entrambe le estremità della settimana, ma suppongo che potrebbe essere il male minore. Grazie non meno. – JackLeo

+1

Sì, non tutte le parti della tua app devono essere idonee al codice del golf. A volte devi fare un percorso più lungo. Fai sempre ciò che è più semplice, più ovvio e crea il minimo ingombro (modificando il modo in cui Django maneggia i filtri lascerebbe un'impronta enorme). –

1

(Questa risposta dovrebbe funzionare solo per Postgres, ma potrebbe funzionare per altri database.)

Una soluzione rapida ed elegante per questo problema potrebbe essere quella di definire questi due custom transformers:

from django.db import models 
from django.db.models.lookups import DateTransform 

@models.DateTimeField.register_lookup 
class WeekTransform(DateTransform): 
    lookup_name = 'week' 


@models.DateTimeField.register_lookup 
class ISOYearTransform(DateTransform): 
    lookup_name = 'isoyear' 

Ora può interrogare per settimana in questo modo:

from django.utils.timezone import now 
year, week, _ = now().isocalendar() 

MyModel.objects.filter(created__isoyear=year, created__week=week) 

sedere le scene, l'oggetto Django DateTransform utilizza i postgres EXTRACT function, che s upports week e isoyear.

0

ExtractWeek è stato introdotto in Django 1.11 per il filtraggio basato sul numero di isoweek.

Per Django 1.10 e inferiori versioni, seguendo soluzione funziona per il filtraggio in base al numero iso settimana nel database Postgres:

from django.db.models.functions import Extract 
from django.db import models 
@models.DateTimeField.register_lookup 
class ExtractWeek(Extract): 
    lookup_name = 'week' 

Ora fare domanda come segue

queryset.annotate(week=ExtractWeek('date'))\ 
      .filter(week=week_number) 
Problemi correlati