2012-05-09 17 views
10

Ich habe ein Modell, das datefield enthält. Ich versuche, Abfrage-Set dieses Modells zu erhalten, das aktuelle Woche enthält (beginnt am Montag).Django Queryset Filterung nach ISO-Woche Nummer

Also, da Django datefield enthält einfach datetime.date Modell nahm ich an, mit .isocalendar() zu filtern. Logischerweise ist es genau das, was ich ohne zusätzliche Vergleiche und Berechnungen bis zum aktuellen Wochentag möchte.

Also, was soll ich im Wesentlichen tun, ist Kraft .filter Aussage in dieser Logik zu verhalten:

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

Doch wie es in Filteranweisung zu schreiben? .filter(model__date__isocalendar=datetime.date.today().isocalendar()) wird falsche Ergebnisse geben (wie im Vergleich zu heute nicht diese Woche).

Als Graben wahr http://docs.python.org/library/datetime.html ich alle anderen Wochentag Optionen nicht bemerkt haben ...

Hinweis aus Dokumentation:

date.isocalendar() Gibt ein 3-Tupel (ISO Jahr , ISO-Wochennummer, ISO Wochentag).

Update:

Obwohl ich die Lösung der Verwendung reicht nicht mochte aber es ist die beste Option. In meinem Fall habe ich jedoch eine Variable erstellt, die den Beginn der Woche markiert und einfach größer oder gleichwertig aussieht, wenn ich nach einem Match für die aktuelle Woche suche. Im Falle der Angabe der Zahl der Woche würde es beide Enden erfordern.

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

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

folgt Ich weiß nicht, ob die ORM-Unterstützung, die aber Sie können Rückfall zu Rohabfrage, wenn es nicht tut https://docs.djangoproject.com/en/dev/topics/db/sql/ – dm03514

+0

Ich bin mir dieser Option dm03514 bewusst, aber ich würde lieber meinen eigenen Filter dann schreiben. Das ist auch eine Option, aber ich möchte wissen, ob es möglich ist, dies mit Standardaktionen in Django zu erreichen, ohne es zu erweitern. – JackLeo

+1

BTW gibt es schön Python-Dateutil-Modul, das hilfreich sein könnte http://pypi.python.org/pypi/python-dateutil – aisbaa

Antwort

8

Sie werden nicht in der Lage sein, dies zu tun. Denken Sie daran, dass es nicht nur eine Frage dessen ist, was Python unterstützt, sondern dass Django den Filter an die Datenbank übermitteln muss und die Datenbank solche komplexen Datumsberechnungen nicht unterstützt. Sie können verwenden __range, obwohl mit einem Startdatum und Enddatum.

+0

Ja, ich würde auch * __ Bereich *, vielleicht Event benutzerdefinierte ModelManager und benutzerdefinierte Queryset mit * Woche (date_field = (2012, 18)) * Methode. – aisbaa

+0

Ich weiß über Bereich Option, aber ich vermied es aufgrund der Anzahl der Aktionen, die erforderlich ist, um beide Enden der Woche zu bekommen, aber ich denke, dass das kleinere Übel sein kann. Danke nicht weniger. – JackLeo

+1

Ja, nicht jeder Teil Ihrer App muss Code-fähig sein. Manchmal muss man einen längeren Weg nehmen. Mache immer das Einfachste, Offensichtlichste und erschaffe den geringsten Footprint (das Modifizieren, wie Django mit Filtern umgeht, würde einen ziemlich großen Fußabdruck hinterlassen). –

1

(Diese Antwort nur für Postgres funktionieren sollte, aber vielleicht für andere Datenbanken arbeiten.)

Eine schnelle und elegante Lösung für dieses Problem, diese beiden custom transformers zu definieren wäre: Sie

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' 

Jetzt Abfrage kann dies durch Woche wie:

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

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

Behinds die Kulissen, verwendet das Django DateTransform Objekt die postgres EXTRACT function, die s Upports week und isoyear.

0

ExtractWeek wurde in Django 1.11 zum Filtern basierend auf der isoweek-Nummer eingeführt.

Für Django 1.10 und niedrigeren Versionen, Lösung folgende Arbeiten zur Filterung von iso-Nummer Woche auf Postgres-Datenbank:

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

Jetzt Abfrage tun als

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