2012-05-09 58 views
10

tengo un modelo que contiene datefield. Estoy tratando de obtener el conjunto de consultas de ese modelo que contiene la semana actual (comienza el lunes).Django filtrado queryset por número de semana ISO

Así que desde Django datefield contiene el modelo simple datetime.date que supuse filtrar usando .isocalendar(). Lógicamente es exactamente lo que quiero sin tener que hacer comparaciones y cálculos adicionales por día de la semana actual.

Así que lo que quiero hacer es esencialmente la fuerza .filter comunicado a comportarse de esta lógica:

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

Sin embargo, la forma de escribir dentro de instrucción de filtro? .filter(model__date__isocalendar=datetime.date.today().isocalendar()) dará resultados erróneos (igual que en comparación con hoy en día no esta semana).

como cavar cierto http://docs.python.org/library/datetime.html no he notado ninguna otra opción semana del día ...

Nota de documentación:

date.isocalendar() Devuelve una tupla de 3, (ISO año , Número de semana ISO, ISO entre semana).

Actualización:

Aunque no me gustaba la solución de utilizar rangos sin embargo, es la mejor opción. Sin embargo, en mi caso hice una variable que marca el comienzo de la semana y con tan sólo mirar igual o mayor valor, porque si yo estoy buscando unos resultados para la semana actual. En caso de dar el número de la semana, requeriría ambos extremos.

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

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

Yo no sé si el apoyo ORM eso, sino que puede repliegue a la consulta sin formato si no lo hace https://docs.djangoproject.com/en/dev/topics/db/sql/ – dm03514

+0

Conozco esta opción dm03514, pero prefiero escribir mi propio filtro. Esa también es una opción, pero estoy preguntando si es posible lograr esto usando acciones predeterminadas en Django sin extenderlo. – JackLeo

+1

por cierto hay un bonito módulo dateutil de python que podría ser útil http://pypi.python.org/pypi/python-dateutil – aisbaa

Respuesta

8

No vas a poder hacer esto. Recuerde que no es solo un problema de lo que Python admite, Django tiene que comunicar el filtro a la base de datos, y la base de datos no es compatible con tales cálculos complejos de fechas. Usted puede __range utilizar, sin embargo, con una fecha de inicio y de finalización.

+0

Sí, también usaría * __ range *, tal vez agregará un ModelManager personalizado y un Queryset personalizado con * week (date_field = (2012, 18)) * método. – aisbaa

+0

Sé acerca de la opción de rango, sin embargo, lo estaba evitando debido a la cantidad de acciones que se requieren para obtener los dos extremos de la semana, pero creo que ese puede ser el mal menor. Gracias no menos. – JackLeo

+1

Sí, no todas las partes de su aplicación deben ser elegibles para el código de golf. A veces tienes que tomar un camino más largo. Haga siempre lo que es más simple, más obvio y crea la menor huella (modificar cómo Django maneja los filtros dejaría una gran huella). –

1

(Esta respuesta sólo debe trabajar para Postgres, pero podría funcionar para otras bases de datos.)

Una solución rápida y elegante para este problema sería definir estos dos 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' 

Ahora se puede consultar en la semana siguiente manera:

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

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

Behinds las escenas, el objeto Django DateTransform utiliza los postgres EXTRACT function, que s upports week y isoyear.

0

ExtractWeek se ha introducido en Django 1.11 para el filtrado basado en el número isoweek.

Para Django 1.10 e inferior versiones, la solución siguiente funciona para filtrar por número iso semana en la base de datos postgres:

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

Ahora haz consulta de la siguiente

queryset.annotate(week=ExtractWeek('date'))\ 
      .filter(week=week_number) 
Cuestiones relacionadas