Django-fr

Forum

#1 16-09-2012 10:29:12

bibou
Membre
Inscription : 13-10-2010
Messages : 7

probleme de filter query

Bonjour les experts django.

voilà, je bute sur un query filter:
j'ai défini dans models.py 2 objets (Tache et Todo qui a une ForeignKey
vers Tache)

class Tache(models.Model):
    nom = models.CharField(max_length=40, blank=True)
    description = models.CharField(max_length=100, blank=True)
    delai = models.IntegerField(null=True, blank=True)

class Todo(models.Model):
    status = models.CharField(max_length=1, default="0")
    tache = models.ForeignKey(Tache)
    datecreation = models.DateTimeField(blank=True, null=True)
    datelimite = models.DateTimeField(null=True, blank=True)

Je veux sélectionner tous les Todo dont la datelimite est inférieur ou
egale à la date du jour + le delai (qui et un nombre de jours défini dans
Tache)
voila ce que je fait et qui ne fonctionne pas:

today = datetime.now()
todos = Todo.objects.filter(datelimite__lte=today +
timedelta(days=tache__delai))

j'ai une erreur du style : NameError : tache__delai is not defined.

Une idée ?

Hors ligne

#2 16-09-2012 10:37:21

ksamuel
Modérateur
Inscription : 22-06-2012
Messages : 40
Site Web

Re : probleme de filter query

Je pense que tu cherches ça:

https://docs.djangoproject.com/en/1.4/topics/db/queries/#filters-can-reference-fields-on-the-model

Le dim. 16 sept. 2012 11:29:12 CEST, Franck PUJOL a écrit :
> Bonjour les experts django.
>
> voilà, je bute sur un query filter:
> j'ai défini dans models.py 2 objets (Tache et Todo qui a une
> ForeignKey vers Tache)
>
> class Tache(models.Model):
>     nom = models.CharField(max_length=40, blank=True)
>     description = models.CharField(max_length=100, blank=True)
>     delai = models.IntegerField(null=True, blank=True)
>
> class Todo(models.Model):
>     status = models.CharField(max_length=1, default="0")
>     tache = models.ForeignKey(Tache)
>     datecreation = models.DateTimeField(blank=True, null=True)
>     datelimite = models.DateTimeField(null=True, blank=True)
>
> Je veux sélectionner tous les Todo dont la datelimite est inférieur ou
> egale à la date du jour + le delai (qui et un nombre de jours défini
> dans Tache)
> voila ce que je fait et qui ne fonctionne pas:
>
> today = datetime.now()
> todos = Todo.objects.filter(datelimite__lte=today +
> timedelta(days=tache__delai))
>
> j'ai une erreur du style : NameError : tache__delai is not defined.
>
> Une idée ?
>
>
>
>
>
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django

Hors ligne

#3 16-09-2012 10:53:38

bibou
Membre
Inscription : 13-10-2010
Messages : 7

Re : probleme de filter query

oui, tu as raison: il faut que j'utilise l'objet F(), le pb c'est que les
exemples sont basiques et j'ai du mal a voir comment utiliser l'objet F()
dans mon exemple précis ou il faut en plus que je suive une relation
(tache__delai)

Le 16 septembre 2012 11:37, Kevin Samuel <kevsamuel _AT_ myopera.com> a écrit :

> Je pense que tu cherches ça:
>
>
> https://docs.djangoproject.com/en/1.4/topics/db/queries/#filters-can-reference-fields-on-the-model
>
> Le dim. 16 sept. 2012 11:29:12 CEST, Franck PUJOL a écrit :
> > Bonjour les experts django.
> >
> > voilà, je bute sur un query filter:
> > j'ai défini dans models.py 2 objets (Tache et Todo qui a une
> > ForeignKey vers Tache)
> >
> > class Tache(models.Model):
> >     nom = models.CharField(max_length=40, blank=True)
> >     description = models.CharField(max_length=100, blank=True)
> >     delai = models.IntegerField(null=True, blank=True)
> >
> > class Todo(models.Model):
> >     status = models.CharField(max_length=1, default="0")
> >     tache = models.ForeignKey(Tache)
> >     datecreation = models.DateTimeField(blank=True, null=True)
> >     datelimite = models.DateTimeField(null=True, blank=True)
> >
> > Je veux sélectionner tous les Todo dont la datelimite est inférieur ou
> > egale à la date du jour + le delai (qui et un nombre de jours défini
> > dans Tache)
> > voila ce que je fait et qui ne fonctionne pas:
> >
> > today = datetime.now()
> > todos = Todo.objects.filter(datelimite__lte=today +
> > timedelta(days=tache__delai))
> >
> > j'ai une erreur du style : NameError : tache__delai is not defined.
> >
> > Une idée ?
> >
> >
> >
> >
> >
> > _______________________________________________
> > django mailing list
> > django _AT_ lists.afpy.org
> > http://lists.afpy.org/mailman/listinfo/django
>
>
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#4 17-09-2012 11:12:01

ksamuel
Modérateur
Inscription : 22-06-2012
Messages : 40
Site Web

Re : probleme de filter query

Arf, j'avais pas vu que le timedelta devais être la référence externe. Là c'est plus compliqué. Je vais consulter les oracles.

Hors ligne

#5 17-09-2012 21:51:59

ksamuel
Modérateur
Inscription : 22-06-2012
Messages : 40
Site Web

Re : probleme de filter query

Bon, y a deux manières possibles:

1 - utiliser 'extra' (probablement non portable)
2 - faire un custom field pour datelimite

1 suppose de grosso modo écrire du sql à la main.

2, il faut faire une classe qui hérite de IntegerField, mais qui accepte une date en entrée, la sauvegarde comme timestamp, et au loading, la reconverti en date. Ainsi la comparaison peut se faire avec F, puisque les timestamps sont juste des entiers.

Hors ligne

#6 18-09-2012 08:39:39

bibou
Membre
Inscription : 13-10-2010
Messages : 7

Re : probleme de filter query

Je vais regarder les 2 pistes que tu proposes.

La 2eme me semble préférable car je préfère autant que possible garder le
côté portabilité.
Merci pour tes investigations

Le 17 septembre 2012 22:51, ksamuel <kevsamuel _AT_ myopera.com> a écrit :

> Bon, y a deux manières possibles:
>
> 1 - utiliser 'extra' (probablement non portable)
> 2 - faire un custom field pour datelimite
>
> 1 suppose de grosso modo écrire du sql à la main.
>
> 2, il faut faire une classe qui hérite de IntegerField, mais qui accepte
> une date en entrée, la sauvegarde comme timestamp, et au loading, la
> reconverti en date. Ainsi la comparaison peut se faire avec F, puisque les
> timestamps sont juste des entiers.
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#7 18-09-2012 09:16:22

Christophe, Jean-Charles Narbonne
Membre
Inscription : 23-06-2011
Messages : 30

Re : probleme de filter query

Bonjour, j'ai pu passer quelques minutes avec Monsieur Pujol  avec de la
VOIP.

Avec PostgreSQL, les dates sont enregistrés en "timestamp with timezone" et
semblent ne pas se comparer à des entiers si facilement.

J'ai vu des customfields qui en effet gérait ça avec des integer mais je ne
suis pas sur que ce soit fonctionnel en production avec postgres et des
dates avec timezone. Ce qui m'a mis la pusse à l'oreille est l'erreur quand
on a essayé:

Todo.objects.filter(datelimite__lte=int(time.mktime(today.timetuple())) +
(F("tache__delai") *3600 * 24))

DatabaseError: ERREUR:  l'opérateur n'existe pas : timestamp with time zone
<= integer

Cordialement,

2012/9/18 Franck PUJOL <franck.pujol _AT_ gmail.com>

> Je vais regarder les 2 pistes que tu proposes.
>
> La 2eme me semble préférable car je préfère autant que possible garder le
> côté portabilité.
> Merci pour tes investigations
>
> Le 17 septembre 2012 22:51, ksamuel <kevsamuel _AT_ myopera.com> a écrit :
>
> Bon, y a deux manières possibles:
>>
>> 1 - utiliser 'extra' (probablement non portable)
>> 2 - faire un custom field pour datelimite
>>
>> 1 suppose de grosso modo écrire du sql à la main.
>>
>> 2, il faut faire une classe qui hérite de IntegerField, mais qui accepte
>> une date en entrée, la sauvegarde comme timestamp, et au loading, la
>> reconverti en date. Ainsi la comparaison peut se faire avec F, puisque les
>> timestamps sont juste des entiers.
>> _______________________________________________
>> django mailing list
>> django _AT_ lists.afpy.org
>> http://lists.afpy.org/mailman/listinfo/django
>>
>
>
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#8 18-09-2012 12:08:01

Chamal
Membre
Inscription : 11-08-2010
Messages : 17

Re : probleme de filter query

Le 18 sept. 2012 à 10:16, Christophe Narbonne <christophe31 _AT_ gmail.com> a écrit :

> Bonjour, j'ai pu passer quelques minutes avec Monsieur Pujol  avec de la VOIP.
>
> Avec PostgreSQL, les dates sont enregistrés en "timestamp with timezone" et semblent ne pas se comparer à des entiers si facilement.

Effectivement la comparaison des types timestamp et integer n'est pas possible. Par contre il est possible de comparer un timestamp
avec un char (qui sera cast automatiquement en timestamp), et les opérateurs >, <, =, between et variantes fonctionnent, par ex:

select * from table where date_created >= '2012-01-01 23:59:00';

>
> J'ai vu des customfields qui en effet gérait ça avec des integer mais je ne suis pas sur que ce soit fonctionnel en production avec postgres et des dates avec timezone. Ce qui m'a mis la pusse à l'oreille est l'erreur quand on a essayé:
>
> Todo.objects.filter(datelimite__lte=int(time.mktime(today.timetuple())) + (F("tache__delai") *3600 * 24))

En exprimant l'objet datetime en str plutôt qu'int la comparaison est possible,
ca doit donner quelque chose du genre :
Todo.objects.filter(datelimite__lte=(today + timedelta(day=F(tache__delai)).isoformat())

Si le format produit par la méthode datetime.isoformat() ne fonctionne pas,
voir a utiliser strftime('%Y-%m%-d %T') (plus l'éventuelle timezone)

Hors ligne

#9 18-09-2012 20:02:14

Christophe, Jean-Charles Narbonne
Membre
Inscription : 23-06-2011
Messages : 30

Re : probleme de filter query

Merci Aymeric pour cette information fort intéressante, je pense que
pouvoir gérer des char peut être intéressant.
néanmoins, timedelta(day=) ne peut techniquement pas prendre de
django.db.models.F en argument.

timedelta est d'une bibliothèque python standart quand F est de django et
interprété sur la base de donnée.

Ça donne une piste de recherche intéressante de plus.

2012/9/18 Aymeric Barantal <mric _AT_ chamal.fr>

>
> Le 18 sept. 2012 à 10:16, Christophe Narbonne <christophe31 _AT_ gmail.com> a
> écrit :
>
> > Bonjour, j'ai pu passer quelques minutes avec Monsieur Pujol  avec de la
> VOIP.
> >
> > Avec PostgreSQL, les dates sont enregistrés en "timestamp with timezone"
> et semblent ne pas se comparer à des entiers si facilement.
>
> Effectivement la comparaison des types timestamp et integer n'est pas
> possible. Par contre il est possible de comparer un timestamp
> avec un char (qui sera cast automatiquement en timestamp), et les
> opérateurs >, <, =, between et variantes fonctionnent, par ex:
>
> select * from table where date_created >= '2012-01-01 23:59:00';
>
> >
> > J'ai vu des customfields qui en effet gérait ça avec des integer mais je
> ne suis pas sur que ce soit fonctionnel en production avec postgres et des
> dates avec timezone. Ce qui m'a mis la pusse à l'oreille est l'erreur quand
> on a essayé:
> >
> > Todo.objects.filter(datelimite__lte=int(time.mktime(today.timetuple()))
> + (F("tache__delai") *3600 * 24))
>
> En exprimant l'objet datetime en str plutôt qu'int la comparaison est
> possible,
> ca doit donner quelque chose du genre :
> Todo.objects.filter(datelimite__lte=(today +
> timedelta(day=F(tache__delai)).isoformat())
>
> Si le format produit par la méthode datetime.isoformat() ne fonctionne pas,
> voir a utiliser strftime('%Y-%m%-d %T') (plus l'éventuelle timezone)
>
> --
> Aymeric Barantal
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

Pied de page des forums