J'essaie de filtrer une DateTimeField
par rapport à une date. Je veux dire:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
Je reçois une liste de requêtes vide comme réponse car (je pense), je ne considère pas le temps, mais je veux "n'importe quand".
Y a-t-il un moyen facile de faire cela à Django?
J'ai l'heure dans l'heure fixée, ce n'est pas 00:00
.
Ces recherches sont implémentées dans Django.views.generic.date_based
comme suit:
{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}
Comme il est assez détaillé, il est prévu d'améliorer la syntaxe en utilisant l'opérateur __date
. Cochez l'option " # 9596. Comparer un DateTimeField à une date est trop difficile " pour plus de détails.
YourModel.objects.filter(datetime_published__year='2008',
datetime_published__month='03',
datetime_published__day='27')
// éditer après les commentaires
YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))
ne fonctionne pas car il crée un objet datetime avec des valeurs d'heure définies sur 0; l'heure dans la base de données ne correspond donc pas.
Voici les résultats obtenus avec la fonction timeit d'ipython:
from datetime import date
today = date.today()
timeit[Model.objects.filter(date_created__year=today.year, date_created__month=today.month, date_created__day=today.day)]
1000 loops, best of 3: 652 us per loop
timeit[Model.objects.filter(date_created__gte=today)]
1000 loops, best of 3: 631 us per loop
timeit[Model.objects.filter(date_created__startswith=today)]
1000 loops, best of 3: 541 us per loop
timeit[Model.objects.filter(date_created__contains=today)]
1000 loops, best of 3: 536 us per loop
contient semble être plus rapide.
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))
ce qui précède est ce que j'ai utilisé. Non seulement cela fonctionne-t-il, mais il possède également un support logique inhérent.
Django dispose maintenant du filtre __date queryset pour interroger les objets datetime par rapport aux dates dans la version de développement. Ainsi, il sera bientôt disponible en 1.9.
Cela produit les mêmes résultats qu'en utilisant __year, __month et __day et semble fonctionner pour moi:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
A partir de Django 1.9, la solution consiste à utiliser __date
sur un objet datetime.
Par exemple: MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))
en supposant que active_on soit un objet de date, incrémentez-le d'un jour puis faites-le
next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )
Voici une technique intéressante: j'ai exploité la procédure startswith mise en œuvre avec Django sur MySQL pour obtenir le résultat qui consiste à ne rechercher qu'une date-heure au travers de la date uniquement. Fondamentalement, lorsque Django effectue la recherche dans la base de données, il doit effectuer une conversion de chaîne pour l'objet de stockage DATETIME MySQL. Vous pouvez ainsi filtrer sur celui-ci, en omettant la partie timestamp de la date. Ainsi,% LIKE% correspond uniquement à la date. objet et vous aurez chaque horodatage pour la date donnée.
datetime_filter = datetime(2009, 8, 22)
MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
Ceci effectuera la requête suivante:
SELECT (values) FROM myapp_my_object \
WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
LIKE BINARY dans ce cas correspondra à tout pour la date, quel que soit l'horodatage. Y compris des valeurs telles que:
+---------------------+
| datetime_attr |
+---------------------+
| 2009-08-22 11:05:08 |
+---------------------+
J'espère que cela aidera tout le monde jusqu'à ce que Django propose une solution!
Hm .. Ma solution fonctionne:
Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
Un article de blog fantastique couvre ce sujet ici: Comparaison de dates et de dates dans l'ORM de Django
La meilleure solution pour Django> 1.7, <1.9 consiste à enregistrer une transformation:
from Django.db import models
class MySQLDatetimeDate(models.Transform):
"""
This implements a custom SQL lookup when using `__date` with datetimes.
To enable filtering on datetimes that fall on a given date, import
this transform and register it with the DateTimeField.
"""
lookup_name = 'date'
def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs)
return 'DATE({})'.format(lhs), params
@property
def output_field(self):
return models.DateField()
Ensuite, vous pouvez l’utiliser dans vos filtres comme ceci:
Foo.objects.filter(created_on__date=date)
MODIFIER
Cette solution est définitivement dépendante. De l'article:
Bien entendu, cette implémentation repose sur votre propre style SQL ayant une fonction DATE (). MySQL fait. SQLite aussi. D’autre part, je n’ai pas travaillé personnellement avec PostgreSQL, mais certaines recherches sur Google me font penser qu’il n’a pas de fonction DATE (). Donc, une implémentation aussi simple semble vouloir être dépendante de l’arrière-plan.
Voir l'article Documentation Django
C'est très similaire à la réponse JZ
ur_data_model.objects.filter(ur_date_field=datetime(2005, 7, 27)
Dans Django 1.7.6 fonctionne:
MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)