web-dev-qa-db-fra.com

Comment filtrer une date d'un DateTimeField dans Django?

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.

147
Xidobix

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.

105
Piotr Czapla
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.

89
zalew

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.

74
Moreno
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.

35
kettlehell

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.

35
omat

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))
24
mhost

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))

21
Andrew B.

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) )
7
davidj411

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!

2
bbengfort

Hm .. Ma solution fonctionne:

Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
1
satels

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.

0
Dan Gayle

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)
0
shahjapan

Dans Django 1.7.6 fonctionne:

MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
0
FACode
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
0
Skylar Saveland