django: DateDiff query SQL?
Domanda
Sto cercando di fare l'equivalente del seguente SQL in Django:
SELECT * FROM WHERE richiedente date_out - date_in> = 1, date_out - date_in <= 6
posso fare questo come RAW query SQL, ma questo sta diventando frustrante nel trattare con un RawQuerySet invece di un oggetto QuerySet regolare come mi piacerebbe essere in grado di filtrare in un secondo momento nel codice.
Soluzione
È possibile utilizzare il metodo extra()
e passare un argomento where
parola chiave. Il valore di where
dovrebbe essere un elenco che contiene la clausola WHERE
SQL della query precedente. Ho provato questo con PostgreSQL 8.4 e questo è ciò che sembrava nel mio caso:
q = Applicant.objects.extra(where = ["""date_part('day', age(date_out, date_in)) >= 1 and
date_part('day', age(date_out, date_in)) <= 6"""])
Ciò restituirà si un'istanza QuerySet
valido.
Altri suggerimenti
mi sono imbattuto l'emissione di Django non nativamente supporto Datediff
(e di altri equivalenti di database), e aveva bisogno di utilizzare tale funzione un numero di volte per un particolare progetto.
Al momento ulteriore lettura, è apparso chiaro che l'attuazione di calcolare un intervallo di due date molto diversa tra le principali sapori di database. Questo è probabilmente il motivo per cui non ha una funzione di astrazione nativo in Django ancora. Così ho scritto la mia funzione di Django ORM per datediff
:
See: mike-db-tools Github repository
Si vedrà la sintassi che varia tra i database backend scritte nelle docstring per le rispettive banche dati. DateDiff supporti SQLite, MySQL / MariaDB, PostgreSQL e Oracle.
Utilizzo (Django 1.8 +):
from db_tools import Datediff
# Define a new dynamic fields to contain the calculated date difference
applicants = Applicant.objects.annotate(
days_range=Datediff('date_out','date_in', interval='days'),
)
# Now you can use this dynamic field in your standard filter query
applicants = applicants.filter(days_range__gte=1, days_range__lte=6)
Sono davvero molto Derpy quando si tratta di mio codice, quindi vi incoraggio a forcella e migliorare.