Filtrage Django queryset par numéro de la semaine ISO

j'ai un modèle qui contient datefield. J'essaie d'obtenir l'ensemble de requête de ce modèle qui contient la semaine en cours (commence lundi).

donc depuis Django datefield contient simple datetime.date modèle que j'ai supposé filtrer en utilisant .isocalendar(). Logiquement, c'est exactement ce que je veux sans comparaisons et calculs supplémentaires par jour de la semaine en cours.

Donc ce que je veux faire, essentiellement, est à la force .filter déclaration à se comporter de cette logique:

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

Encore comment l'écrire dans la déclaration du filtre? .filter(model__date__isocalendar=datetime.date.today().isocalendar()) donnera des résultats faux (comparer à aujourd'hui, pas cette semaine).

comme creusant vrai http://docs.python.org/library/datetime.html Je n'ai pas remarqué d'autres options de jour de semaine...

Note de la documentation:

date.isocalendar () retourner un 3-tuple, (année ISO, nombre de semaine ISO, ISO semaine.)

mise à Jour:

bien que je n'ai pas aimé la solution de l'utilisation des gammes pourtant c'est la meilleure option. Cependant dans mon cas j'ai fait une variable qui marque le début de la semaine et juste regarder plus ou égale valeur parce que si je suis à la recherche d'un correspond pour la semaine en cours. En cas de donner le nombre de la semaine, il faudrait les deux fins.

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

... 
.filter(date__gte=monday)
10
demandé sur JackLeo 2012-05-09 18:22:46

3 réponses

Vous n'allez pas être en mesure de le faire. Rappelez-vous que ce N'est pas seulement une question de ce que Python supporte, Django doit communiquer le filtre à la base de données, et la base de données ne supporte pas des calculs de date aussi complexes. Vous utiliser __range cependant, avec une date de début et date de fin.

8
répondu Chris Pratt 2012-05-09 14:35:06

(Cette réponse ne doit travailler pour postgres, mais pourrait fonctionner pour d'autres bases de données.)

une solution rapide et élégante pour ce problème serait de définir ces deux transformateurs sur mesure:

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'

Maintenant, vous pouvez faire une requête par semaine comme ceci:

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

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

derrière les scènes, le Django DateTransform l'objet utilise les postgres EXTRACT function, qui prend en charge week et isoyear.

1
répondu Yotam Ofek 2016-05-01 15:03:46

ExtractWeek a été introduit dans Django 1.11 Pour le filtrage basé sur le numéro isoweek.

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

Maintenant faire la requête comme suit

queryset.annotate(week=ExtractWeek('date'))\
            .filter(week=week_number)
1
répondu Amit Jaiswal 2016-11-26 16:00:16